作者:微信小助手
<p style="white-space: normal;max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;" data-mpa-powered-by="yiban.io"><span style="color: rgb(62, 62, 62);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;letter-spacing: 0.544px;text-align: left;word-spacing: 1px;background-color: rgb(255, 255, 255);">往期热门文章:</span></p> <h4 style="color: rgb(62, 62, 62);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;white-space: normal;word-spacing: 1px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);"> <section style="margin-top: 10px;margin-bottom: 10px;font-size: 15px;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;text-indent: 0em;text-align: left;"> <span style="font-size: 14px;">1、</span> <a href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247489898&idx=1&sn=5c5e41a0f695649046de3db1b1810df5&chksm=e9c5e0dbdeb269cd52f798c675f58295ad0f632283c0fb07db4140949c72796deed7dfe7d434&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="color: rgb(62, 62, 62);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;letter-spacing: 0.544px;font-size: 14px;">《</a> <a href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247489402&idx=2&sn=af5c3bb38717e828d92ed48874f03fe8&chksm=e9c5eecbdeb267dd3d05c159bdb9c611f24c4ca7fb7dafa12daf459becb0ef4fab7bcc2d1a67&scene=21#wechat_redirect" target="_blank" data-linktype="2" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;"><span style="font-size: 14px;">往期</span><span style="cursor: pointer;letter-spacing: 0.544px;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);font-size: 14px;">精选优秀博文都在这里了!</span><span style="cursor: pointer;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);letter-spacing: 0.544px;">》</span></a> </section> <section style="margin-top: 10px;margin-bottom: 10px;font-size: 15px;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;text-indent: 0em;text-align: left;"> <span style="font-size: 14px;">2、<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247491273&idx=1&sn=0e90c3dbe316c4a808611cd1f09abb26&chksm=e9c5e778deb26e6ee480638f66afb4d7012a703c12a9c8d16ce097360c14d5230c8e55337571&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">start.aliyun.com 正式上线!极速构建 Spring Cloud 应用</a></span> </section> <section style="margin-top: 10px;margin-bottom: 10px;font-size: 15px;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;text-indent: 0em;text-align: left;"> <span style="font-size: 14px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247491262&idx=1&sn=ee6d9ede43afd66698992e165d4a3a04&chksm=e9c5e70fdeb26e19a84bb3afd491c84638ab1a8d9f23694d8767cc00173ba6ae6deeef4ab3a2&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">3、腾讯和阿里在B站“打起来了”,你何时见过这场面?</a></span> </section> <section style="margin-top: 10px;margin-bottom: 10px;font-size: 15px;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;text-indent: 0em;text-align: left;"> <span style="font-size: 14px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247491250&idx=1&sn=bcd07a204a0cd701544bdc363e8694dc&chksm=e9c5e703deb26e158cd20abd9ce02f10f18601ac375a7f185717e0243e850d54362706048402&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">4、面试必备41道 SpringBoot 面试题,不看亏大了!</a></span> </section> <section style="margin-top: 10px;margin-bottom: 10px;font-size: 15px;font-variant-numeric: normal;font-variant-east-asian: normal;letter-spacing: 0.544px;widows: 1;caret-color: rgb(255, 0, 0);line-height: 1.75em;text-indent: 0em;text-align: left;"> <span style="font-size: 14px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247491221&idx=1&sn=598fac36c967b6968667251e64955025&chksm=e9c5e724deb26e32adba7e650bb4664c26cb7b669b7f620fc89ce0b283f98363a5bca9367b88&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;">5、差距大,没想到成人网站用的技术都甩我们几条街!</a></span> </section></h4> <section style="white-space: normal;margin-top: 15px;"> <span style="font-size: 13px;">本文来源公众号:码洞</span> </section> <p style="white-space: normal;"><span style="font-size: 13px;">原文作者:卢玮,掌阅资深后端工程师</span></p> <h1 style="margin-bottom: 16px;padding-bottom: 0.3em;font-weight: 600;font-size: 2em;max-width: 100%;box-sizing: border-box;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;border-bottom: 1px solid rgb(234, 236, 239);color: rgb(36, 41, 46);background-color: rgb(255, 255, 255);line-height: 2em;overflow-wrap: break-word !important;"><span style="font-size: 15px;color: rgb(255, 76, 65);">为什么引入</span><br></h1> <p style="margin-bottom: 16px;max-width: 100%;box-sizing: border-box;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;color: rgb(36, 41, 46);text-align: start;background-color: rgb(255, 255, 255);line-height: 2em;overflow-wrap: break-word !important;"><span style="font-size: 15px;">我们的业务中经常会遇到穿库的问题,通常可以通过缓存解决。如果数据维度比较多,结果数据集合比较大时,缓存的效果就不明显了。</span></p> <p style="margin-bottom: 16px;max-width: 100%;box-sizing: border-box;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;color: rgb(36, 41, 46);text-align: start;background-color: rgb(255, 255, 255);line-height: 2em;overflow-wrap: break-word !important;"><span style="font-size: 15px;">因此为了解决穿库的问题,我们引入Bloom Filter。</span></p> <h2 style="margin-top: 24px;margin-bottom: 16px;padding-bottom: 0.3em;font-weight: 600;font-size: 1.5em;max-width: 100%;box-sizing: border-box;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;border-bottom: 1px solid rgb(234, 236, 239);color: rgb(36, 41, 46);background-color: rgb(255, 255, 255);line-height: 2em;overflow-wrap: break-word !important;"><span style="font-size: 15px;color: rgb(255, 76, 65);">适合的场景</span></h2> <ul class="list-paddingleft-2" style=""> <li><p style="margin-top: 16px;margin-bottom: 16px;max-width: 100%;box-sizing: border-box;min-height: 1em;line-height: 2em;overflow-wrap: break-word !important;"><span style="font-size: 15px;">数据库防止穿库 Google Bigtable,Apache HBase和Apache Cassandra以及Postgresql 使用BloomFilter来减少不存在的行或列的磁盘查找。</span></p><p style="margin-top: 16px;margin-bottom: 16px;max-width: 100%;box-sizing: border-box;min-height: 1em;line-height: 2em;overflow-wrap: break-word !important;"><span style="font-size: 15px;">避免代价高昂的磁盘查找会大大提高数据库查询操作的性能。如同一开始的业务场景。如果数据量较大,不方便放在缓存中。需要对请求做拦截防止穿库。</span></p></li> <li><p style="margin-top: 16px;margin-bottom: 16px;max-width: 100%;box-sizing: border-box;min-height: 1em;line-height: 2em;overflow-wrap: break-word !important;"><span style="font-size: 15px;">缓存宕机 缓存宕机的场景,使用布隆过滤器会造成一定程度的误判。</span></p><p style="margin-top: 16px;margin-bottom: 16px;max-width: 100%;box-sizing: border-box;min-height: 1em;line-height: 2em;overflow-wrap: break-word !important;"><span style="font-size: 15px;">原因是除了Bloom Filter 本身有误判率,宕机之前的缓存不一定能覆盖到所有DB中的数据,当宕机后用户请求了一个以前从未请求的数据,这个时候就会产生误判。</span></p><p style="margin-top: 16px;margin-bottom: 16px;max-width: 100%;box-sizing: border-box;min-height: 1em;line-height: 2em;overflow-wrap: break-word !important;"><span style="font-size: 15px;">当然,缓存宕机时使用布隆过滤器作为应急的方式,这种情况应该也是可以忍受的。</span></p></li> <li style="font-size: 15px;"><p style="margin-top: 16px;margin-bottom: 16px;max-width: 100%;box-sizing: border-box;min-height: 1em;line-height: 2em;overflow-wrap: break-word !important;"><span style="font-size: 15px;">WEB拦截器 相同请求拦截防止被攻击。用户第一次请求,将请求参数放入BloomFilter中,当第二次请求时,先判断请求参数是否被BloomFilter命中。可以提�
作者:微信小助手
<section style="font-size: 14px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;" data-mpa-powered-by="yiban.io"> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;color: rgb(62, 62, 62);background-color: rgb(255, 255, 255);text-size-adjust: auto;font-size: 15px;word-spacing: 2px;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">点击蓝色“</span><span style="max-width: 100%;letter-spacing: 0.544px;font-size: 14px;color: rgb(0, 128, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">架构文摘</span><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(136, 136, 136);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">”关注我哟</span></p> <p style="margin-bottom: 10px;max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;color: rgb(62, 62, 62);background-color: rgb(255, 255, 255);text-size-adjust: auto;font-size: 15px;word-spacing: 2px;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">加个“</span><span style="max-width: 100%;color: rgb(0, 128, 255);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">星标</span><span style="max-width: 100%;font-size: 14px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;">”,每天上午 09:25,干货推送!</span></p> <p style="max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;color: rgb(62, 62, 62);font-size: 14px;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-backh="36" data-backw="578" data-ratio="0.0625" data-s="300,640" data-type="jpeg" data-w="640" width="100%" src="/upload/8c292e55ba5a23cb6ebc11f2a2c4fece.null" style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;widows: 1;word-spacing: 2px;color: rgb(136, 136, 136);box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 677px !important;"></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><strong style="font-size: inherit;color: inherit;line-height: inherit;">本文所有内容基于:</strong><br></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="padding: 2px 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);line-height: 18px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">Docker-CE<br>Server Version: 18.09.6<br>Storage Driver: overlay2<br>Kernel Version: 3.10.0-862.el7.x86_64<br>Operating System: CentOS Linux 7 (Core)<br></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">Docker 日志分为两类:</p> <ul style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 32px;" class="list-paddingleft-2"> <li style="font-size: inherit;color: inherit;line-height: inherit;margin-bottom: 0.5em;"><p><span style="font-size: inherit;color: inherit;line-height: inherit;">Docker 引擎日志(也就是 dockerd 运行时的日志),</span></p></li> <li style="font-size: inherit;color: inherit;line-height: inherit;margin-bottom: 0.5em;"><p><span style="font-size: inherit;color: inherit;line-height: inherit;">容器的日志,容器内的服务产生的日志。</span></p></li> </ul> <h2 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.4em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">一 、Docker 引擎日志</span></h2> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">Docker 引擎日志一般是交给了 Upstart(Ubuntu 14.04) 或者 systemd (CentOS 7, Ubuntu 16.04)。前者一般位于 /var/log/upstart/docker.log 下,后者我们一般 通过 <code style="font-size: inherit;line-height: inherit;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">journalctl -u docker</code> 来进行查看。</p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">| 系统 |</span> 日志位置 <span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">|<br>|</span> ---------------------- <span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">| ------------------------------------------------------------ |</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">| Ubuntu(14.04) |</span> <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">`/var/log/upstart/docker.log`</span> <span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">|<br>|</span> Ubuntu(<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">16.04</span>) <span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">| `journalctl -u docker.service` |</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">| CentOS 7/RHEL 7/Fedora |</span> <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">`journalctl -u docker.service`</span> <span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">|<br>|</span> CoreOS <span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">| `journalctl -u docker.service` |</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">| OpenSuSE |</span> <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">`journalctl -u docker.service`</span> <span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">|<br>|</span> OSX <span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">| `~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/log/docker.log` |</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">| Debian GNU/Linux 7 |</span> <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">`/var/log/daemon.log`</span> <span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">|<br>|</span> Debian GNU/Linux <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">8</span> <span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">| `journalctl -u docker.service` |</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">| Boot2Docker |</span> <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">`/var/log/docker.log`</span> <span style="font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">|<br></span></code></pre> <blockquote style="line-height: inherit;padding: 15px 15px 15px 1rem;font-size: 0.9em;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);background: rgb(242, 247, 251);overflow: auto;overflow-wrap: normal;word-break: normal;"> <p style="font-size: inherit;color: inherit;line-height: inherit;">以上内容来自:https://blog.lab99.org/post/docker-2016-07-14-faq.html</p> </blockquote> <h2 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.4em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">二、容器日志</span></h2> <h3 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.3em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">2.1、常用查看日志命令——docker logs</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><code style="font-size: inherit;line-height: inherit;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">docker logs CONTAINER</code> 显示当前运行的容器的日志信息, UNIX 和 Linux 的命令有三种 输入输出,分别是 STDIN(标准输入)、STDOUT(标准输出)、STDERR(标准错误输出),docker logs 显示的内容包含 STOUT 和 STDERR。在生产环境,如果我们的应用输出到我们的日志文件里,所以我们在使用 docker logs 一般收集不到太多重要的日志信息。</p> <blockquote style="line-height: inherit;padding: 15px 15px 15px 1rem;font-size: 0.9em;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);background: rgb(242, 247, 251);overflow: auto;overflow-wrap: normal;word-break: normal;"> <ul style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 32px;" class="list-paddingleft-2"> <li style="font-size: inherit;color: inherit;line-height: inherit;margin-bottom: 0.5em;"><p>nginx 官方镜像,使用了一种方式,让日志输出到 STDOUT,也就是 创建一个符号链接 <code style="font-size: inherit;line-height: inherit;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">/var/log/nginx/access.log</code> 到 <code style="font-size: inherit;line-height: inherit;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">/dev/stdout</code>。</p></li> <li style="font-size: inherit;color: inherit;line-height: inherit;margin-bottom: 0.5em;"><p>httpd 使用的是 让其输出到指定文件 ,正常日志输出到 <code style="font-size: inherit;line-height: inherit;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">/proc/self/fd/1</code> (STDOUT) ,错误日志输出到 <code style="font-size: inherit;line-height: inherit;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">/proc/self/fd/2</code> (STDERR)。</p></li> <li style="font-size: inherit;color: inherit;line-height: inherit;margin-bottom: 0.5em;"><p><span style="font-size: inherit;color: inherit;line-height: inherit;">当日志量比较大的时候,我们使用 docker logs 来查看日志,会对 docker daemon 造成比较大的压力,容器导致容器创建慢等一系列问题。</span></p></li> <li style="font-size: inherit;color: inherit;line-height: inherit;margin-bottom: 0.5em;"><p><strong style="font-size: inherit;color: inherit;line-height: inherit;">只有使用了 `local 、json-file、journald` 的日志驱动的容器才可以使用 docker logs 捕获日志,使用其他日志驱动无法使用 `docker logs`</strong></p></li> </ul> </blockquote> <h3 style="line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;font-weight: bold;color: rgb(0, 172, 193);font-size: 1.3em;"><span style="font-size: inherit;color: inherit;line-height: inherit;">2.2 、Docker 日志 驱动</span></h3> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">Docker 提供了两种模式用于将消息从容器到日志驱动。</p> <ul style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 32px;" class="list-paddingleft-2"> <li style="font-size: inherit;color: inherit;line-height: inherit;margin-bottom: 0.5em;"><p><span style="font-size: inherit;color: inherit;line-height: inherit;">(默认)拒绝,阻塞从容器到容器驱动</span></p></li> <li style="font-size: inherit;color: inherit;line-height: inherit;margin-bottom: 0.5em;"><p><span style="font-size: inherit;color: inherit;line-height: inherit;">非阻塞传递,日志将储存在容器的缓冲区。</span></p></li> </ul> <blockquote style="line-height: inherit;padding: 15px 15px 15px 1rem;font-size: 0.9em;color: rgb(129, 145, 152);border-left-width: 6px;border-left-color: rgb(220, 230, 240);background: rgb(242, 247, 251);overflow: auto;overflow-wrap: normal;word-break: normal;"> <p style="font-size: inherit;color: inherit;line-height: inherit;">当缓冲区满,旧的日志将被丢弃。</p> </blockquote> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">在 mode 日志选项控制使用 <code style="font-size: inherit;line-height: inherit;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">blocking(默认)</code> 或者 <code style="font-size: inherit;line-height: inherit;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">non-blocking</code>, 当设置为 <code style="font-size: inherit;line-height: inherit;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">non-blocking</code> 需要设置 <code style="font-size: inherit;line-height: inherit;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">max-buffer-size</code> 参数(默认为 1MB)。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">支持的驱动</p> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">| | 描述 |<br>| :----------------------------------------------------------- | :----------------------------------------------------------- |<br>| <span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">`none`</span> | 运行的容器没有日志,<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">`docker logs`</span>也不返回任何输出。 |<br>| [<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">`local`</span>](<span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">https://docs.docker.com/config/containers/logging/local/</span>) | 日志以自定义格式存储,旨在实现最小开销。 |<br>| [<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">`json-file`</span>](<span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">https://docs.docker.com/config/containers/logging/json-file/</span>) | 日志格式为JSON。Docker的默认日志记录驱动程序。 |<br>| [<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">`syslog`</span>](<span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">https://docs.docker.com/config/containers/logging/syslog/</span>) | 将日志消息写入<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">`syslog`</span>。该<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">`syslog`</span>守护程序必须在主机上运行。 |<br>| [<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">`journald`</span>](<span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);overflow-wrap: inherit !important;word-break: inherit !important;">https://docs.docker.com/config/containers/logging/journald/</span>) | 将日志消息写入<span style="font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">`jou
作者:微信小助手
<section style="display: none;" data-tools="新媒体管家" data-label="powered by xmt.cn"> <br> </section> <p style="padding-right: 0.5em;padding-left: 0.5em;white-space: normal;text-align: center;"><img class="rich_pages" data-copyright="0" data-ratio="0.10546875" data-s="300,640" src="/upload/9eb798d67286f62711c373bd36d71b4.png" data-type="png" data-w="1280"></p> <p style="padding-right: 0.5em;padding-left: 0.5em;white-space: normal;text-align: center;"><strong><span style="color: rgb(136, 136, 136);font-size: 12px;letter-spacing: 1px;">总第387篇</span></strong></p> <p style="padding-right: 0.5em;padding-left: 0.5em;white-space: normal;text-align: center;"><strong><span style="color: rgb(136, 136, 136);font-size: 12px;letter-spacing: 1px;">2020年 第10篇</span></strong></p> <section data-role="outer" label="Powered by 135editor.com" style="margin-right: 0.5em;margin-left: 0.5em;padding-right: 0.5em;padding-left: 0.5em;white-space: normal;"> <section data-role="outer" label="Powered by 135editor.com"> <section data-tools="135编辑器" data-id="127" style="border-width: 0px;border-style: none;border-color: initial;"> <section data-tools="135编辑器" data-id="127" style="border-width: 0px;border-style: none;border-color: initial;"> <section style="margin: 60px 16px 16px;border-width: 1px;border-style: solid;border-color: rgb(235, 234, 225);text-align: center;border-radius: 8px;font-weight: inherit;text-decoration: inherit;"> <section style="margin-top: -3.3em;margin-right: 5px;margin-left: 5px;font-size: 18px;color: inherit;"> <section style="margin-right: auto;margin-left: auto;border-width: 2px;border-style: solid;border-color: rgb(235, 234, 225);width: 108px;clear: both;height: 108px;border-radius: 50%;box-shadow: rgb(201, 201, 201) 0px 2px 2px 2px;background-color: rgb(254, 254, 254);"> <img border="0" data-ratio="1" src="/upload/240030e4aa646eba831b1988830c1167.jpg" data-type="jpeg" data-w="800" data-width="100%" height="98" opacity="" style="border-radius: 50%;color: inherit;display: inline-block;width: 98px !important;visibility: visible !important;" title="undefined" width="98"> </section> </section> <section data-brushtype="text" data-style="text-align: left; font-size: 14px; color: inherit;" style="margin: 8px 15px;line-height: 1.4;"> <p style="margin-top: 1.5em;margin-bottom: 1.5em;padding-right: 0.5em;padding-left: 0.5em;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;line-height: inherit;text-align: left;"><span style="font-size: 14px;color: rgb(136, 136, 136);">随着计算机行业的飞速发展,摩尔定律逐渐失效,多核CPU成为主流。使用多线程并行计算逐渐成为开发人员提升服务器性能的基本武器。J.U.C提供的线程池ThreadPoolExecutor类,帮助开发人员管理线程并方便地执行并行任务。了解并合理使用线程池,是一个开发人员必修的基本功。</span></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;padding-right: 0.5em;padding-left: 0.5em;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;line-height: inherit;text-align: left;"><span style="font-size: 14px;color: rgb(136, 136, 136);">本文开篇简述线程池概念和用途,接着结合线程池的源码,帮助读者领略线程池的设计思路,最后回归实践,通过案例讲述使用线程池遇到的问题,并给出了一种动态化线程池解决方案。</span></p> </section> </section> </section> </section> </section> </section> <section style="padding-right: 0.5em;padding-left: 0.5em;letter-spacing: 0px;white-space: normal;font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <section style="line-height: 1.6;letter-spacing: 0px;"> <section style="line-height: 1.6;letter-spacing: 0px;"> <section style="line-height: 1.6;letter-spacing: 0px;"> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="color: rgb(255, 195, 0);"><strong><span style="color: rgb(255, 195, 0);font-size: 20px;">一、写在前面</span></strong></span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 18px;"><strong>1.1 线程池是什么</strong></span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">线程池(</span><span style="font-size: 15px;color: rgb(136, 136, 136);">Thread Pool</span><span style="font-size: 15px;">)是一种基于池化思想管理线程的工具,经常出现在多线程服务器中,如MySQL。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,同时也降低了计算机的整体性能。线程池维护多个线程,等待监督管理者分配可并发执行的任务。这种做法,一方面避免了处理任务时创建销毁线程开销的代价,另一方面避免了线程数量膨胀导致的过分调度问题,保证了对内核的充分利用。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">而本文描述线程池是JDK中提供的ThreadPoolExecutor类。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">当然,使用线程池可以带来一系列好处:</span></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li style="font-size: 15px;"><p><strong><span style="font-size: 15px;">降低资源消耗</span></strong><span style="font-size: 15px;">:通过池化技术重复利用已创建的线程,降低线程创建和销毁造成的损耗。</span></p></li> <li style="font-size: 15px;"><p><strong><span style="font-size: 15px;">提高响应速度</span></strong><span style="font-size: 15px;">:任务到达时,无需等待线程创建即可立即执行。</span></p></li> <li style="font-size: 15px;"><p><strong><span style="font-size: 15px;">提高线程的可管理性</span></strong><span style="font-size: 15px;">:线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。</span></p></li> <li style="font-size: 15px;"><p><strong><span style="font-size: 15px;">提供更多更强大的功能</span></strong><span style="font-size: 15px;">:线程池具备可拓展性,允许开发人员向其中增加更多的功能。比如延时定时线程池ScheduledThreadPoolExecutor,就允许任务延期执行或定期执行。</span></p></li> </ul> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><strong><span style="font-size: 18px;">1.2 线程池解决的问题是什么</span></strong></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">线程池解决的核心问题就是资源管理问题。在并发坏境下,系统不能够确定在任意时刻中,有多少任务需要执行,有多少资源需要投入。这种不确定性将带来以下若干问题:</span></p> <ol class="list-paddingleft-2" style="list-style-type: decimal;"> <li style="font-size: 15px;"><p><span style="font-size: 15px;">频繁申请/销毁资源和调度资源,将带来额外的消耗,可能会非常巨大。</span></p></li> <li style="font-size: 15px;"><p><span style="font-size: 15px;">对资源无限申请缺少抑制手段,易引发系统资源耗尽的风险。</span></p></li> <li style="font-size: 15px;"><p><span style="font-size: 15px;">系统无法合理管理内部的资源分布,会降低系统的稳定性。</span></p></li> </ol> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">为解决资源分配这个问题,线程池采用了“池化”(</span><span style="font-size: 15px;color: rgb(136, 136, 136);">Pooling</span><span style="font-size: 15px;">)思想。池化,顾名思义,是为了最大化收益并最小化风险,而将资源统一在一起管理的一种思想。</span></p> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="207" data-source-title=""> <section class="js_blockquote_digest"> <section> Pooling is the grouping together of resources (assets, equipment, personnel, effort, etc.) for the purposes of maximizing advantage or minimizing risk to the users. The term is used in finance, computing and equipment management.——wikipedia </section> </section> </blockquote> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">“池化”思想不仅仅能应用在计算机领域,在金融、设备、人员管理、工作管理等领域也有相关的应用。</span><br></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">在计算机领域中的表现为:统一管理IT资源,包括服务器、存储、和网络资源等等。通过共享资源,使用户在低投入中获益。除去线程池,还有其他比较典型的几种使用策略包括:</span></p> <ol class="list-paddingleft-2" style="list-style-type: decimal;"> <li style="font-size: 15px;"><p><span style="font-size: 15px;">内存池(</span><span style="font-size: 15px;color: rgb(136, 136, 136);">Memory Pooling</span><span style="font-size: 15px;">):预先申请内存,提升申请内存速度,减少内存碎片。</span></p></li> <li style="font-size: 15px;"><p><span style="font-size: 15px;">连接池(</span><span style="font-size: 15px;color: rgb(136, 136, 136);">Connection Pooling</span><span style="font-size: 15px;">):预先申请数据库连接,提升申请连接的速度,降低系统的开销。</span></p></li> <li style="font-size: 15px;"><p><span style="font-size: 15px;">实例池(</span><span style="font-size: 15px;color: rgb(136, 136, 136);">Object Pooling</span><span style="font-size: 15px;">):循环使用对象,减少资源在初始化和释放时的昂贵损耗。</span></p></li> </ol> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">在了解完“是什么”和“为什么”之后,下面我们来一起深入一下线程池的内部实现原理。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="color: rgb(255, 195, 0);"><strong><span style="color: rgb(255, 195, 0);font-size: 20px;">二、线程池核心设计与实现</span></strong></span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">在前文中,我们了解到:线程池是一种通过“池化”思想,帮助我们管理线程而获取并发性的工具,在Java中的体现是ThreadPoolExecutor类。那么它的的详细设计与实现是什么样的呢?我们会在本章进行详细介绍。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><strong><span style="font-size: 18px;">2.1 总体设计</span></strong></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">Java中的线程池核心实现类是ThreadPoolExecutor,本章基于JDK 1.8的源码来分析Java线程池的核心设计与实现。我们首先来看一下ThreadPoolExecutor的UML类图,了解下ThreadPoolExecutor的继承关系。</span></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 0.5em;padding-right: 0.5em;"> <img data-ratio="1.2510121457489878" src="/upload/e3ba513194a1f918b0abfc42b6fecd0a.png" data-type="png" data-w="247" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;width: 216px;height: 270px;" title="图1 ThreadPoolExecutor UML类图"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> <span style="font-size: 12px;">图1 ThreadPoolExecutor UML类图</span> </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">ThreadPoolExecutor实现的顶层接口是Executor,顶层接口Executor提供了一种思想:将任务提交和任务执行进行解耦。用户无需关注如何创建线程,如何调度线程来执行任务,用户只需提供Runnable对象,将任务的运行逻辑提交到执行器(Executor)中,由Executor框架完成线程的调配和任务的执行部分。ExecutorService接口增加了一些能力:(1)扩充执行任务的能力,补充可以为一个或一批异步任务生成Future的方法;(2)提供了管控线程池的方法,比如停止线程池的运行。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">AbstractExecutorService则是上层的抽象类,将执行任务的流程串联了起来,保证下层的实现只需关注一个执行任务的方法即可。最下层的实现类ThreadPoolExecutor实现最复杂的运行部分,ThreadPoolExecutor将会一方面维护自身的生命周期,另一方面同时管理线程和任务,使两者良好的结合从而执行并行任务。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">ThreadPoolExecutor是如何运行,如何同时维护线程和执行任务的呢?其运行机制如下图所示:</span></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 0.5em;padding-right: 0.5em;"> <img data-ratio="0.43870967741935485" src="/upload/4e788c3de25c337889e31ca0e77ceabd.png" data-type="png" data-w="1085" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="图2 ThreadPoolExecutor运行流程"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> <span style="font-size: 12px;">图2 ThreadPoolExecutor运行流程</span> </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">线程池在内部实际上构建了一个生产者消费者模型,将线程和任务两者解耦,并不直接关联,从而良好的缓冲任务,复用线程。线程池的运行主要分成两部分:任务管理、线程管理。任务管理部分充当生产者的角色,当任务提交后,线程池会判断该任务后续的流转:(1)直接申请线程执行该任务;(2)缓冲到队列中等待线程执行;(3)拒绝该任务。线程管理部分是消费者,它们被统一维护在线程池内,根据任务请求进行线程的分配,当线程执行完任务后则会继续获取新的任务去执行,最终当线程获取不到任务的时候,线程就会被回收。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">接下来,我们会按照以下三个部分去详细讲解线程池运行机制:</span></p> <ol class="list-paddingleft-2" style="list-style-type: decimal;"> <li style="font-size: 15px;"><p><span style="font-size: 15px;">线程池如何维护自身状态。</span></p></li> <li style="font-size: 15px;"><p><span style="font-size: 15px;">线程池如何管理任务。</span></p></li> <li style="font-size: 15px;"><p><span style="font-size: 15px;">线程池如何管理线程。</span></p></li> </ol> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><strong><span style="font-size: 18px;">2.2 生命周期管理</span></strong></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">线程池运行的状态,并不是用户显式设置的,而是伴随着线程池的运行,由内部来维护。线程池内部使用一个变量维护两个值:运行状态(</span><span style="font-size: 15px;color: rgb(136, 136, 136);">runState</span><span style="font-size: 15px;">)和线程数量 (</span><span style="font-size: 15px;color: rgb(136, 136, 136);">workerCount</span><span style="font-size: 15px;">)。在具体实现中,线程池将运行状态(</span><span style="font-size: 15px;color: rgb(136, 136, 136);">runState</span><span style="font-size: 15px;">)、线程数量 (</span><span style="font-size: 15px;color: rgb(136, 136, 136);">workerCount</span><span style="font-size: 15px;">)两个关键参数的维护放在了一起,如下代码所示:</span></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 0.5em;padding-right: 0.5em;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: 12px;"><span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">private</span> <span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">final</span> AtomicInteger ctl = <span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">new</span> AtomicInteger(ctlOf(RUNNING, <span style="line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">0</span>));<br></span></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><code style="font-size: inherit;line-height: inherit;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);"><span style="font-size: 15px;">ctl</span></code><span style="font-size: 15px;">这个AtomicInteger类型,是对线程池的运行状态和线程池中有效线程的数量进行控制的一个字段, 它同时包含两部分的信息:线程池的运行状态 (runState) 和线程池内有效线程的数量 (</span><span style="font-size: 15px;color: rgb(136, 136, 136);">workerCount</span><span style="font-size: 15px;">),高3位保存runState,低29位保存workerCount,两个变量之间互不干扰。用一个变量去存储两个值,可避免在做相关决策时,出现不一致的情况,不必为了维护两者的一致,而占用锁资源。通过阅读线程池源代码也可以发现,经常出现要同时判断线程池运行状态和线程数量的情况。线程池也提供了若干方法去供用户获得线程池当前的运行状态、线程个数。这里都使用的是位运算的方式,相比于基本运算,速度也会快很多。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">关于内部封装的获取生命周期状态、获取线程池线程数量的计算方法如以下代码所示:</span></p> <pre style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 0.5em;padding-right: 0.5em;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: 12px;"><span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">private</span> <span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">static</span> <span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">int</span> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">runStateOf</span><span style="line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">(<span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">int</span> c)</span> </span>{ <span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> c & ~CAPACITY; } <span style="line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">//计算当前运行状态</span><br><span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">private</span> <span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">static</span> <span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">int</span> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">workerCountOf</span><span style="line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">(<span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">int</span> c)</span> </span>{ <span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> c & CAPACITY; } <span style="line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">//计算当前线程数量</span><br><span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;"><span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">private</span> <span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">static</span> <span style="line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;">int</span> <span style="line-height: inherit;color: rgb(165, 218, 45);overflow-wrap: inherit !important;word-break: inherit !important;">ctlOf</span><span style="line-height: inherit;color: rgb(255, 152, 35);overflow-wrap: inherit !important;word-break: inherit !important;">(<span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">int</span> rs, <span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">int</span> wc)</span> </span>{ <span style="line-height: inherit;color: rgb(248, 35, 117);overflow-wrap: inherit !important;word-break: inherit !important;">return</span> rs | wc; } <span style="line-height: inherit;color: rgb(128, 128, 128);overflow-wrap: inherit !important;word-break: inherit !important;">//通过状态和线程数生成ctl</span><br></span></code></pre> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 12px;">ThreadPoolExecutor的运行状态有5种,分别为:</span></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 0.5em;padding-right: 0.5em;"> <img data-cropselx1="0" data-cropselx2="546" data-cropsely1="0" data-cropsely2="156" data-ratio="0.29136690647482016" src="/upload/9ff88b126bf859ccb751ee1526e97f8c.png" data-type="png" data-w="1112" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;width: 546px;height: 159px;" title=""> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">其生命周期转换如下入所示:</span></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 0.5em;padding-right: 0.5em;"> <img data-ratio="0.24886363636363637" src="/upload/1ec0ca2f5213af7e504847dc1d7a9ccb.png" data-type="png" data-w="880" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="图3 线程池生命周期"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> <span style="font-size: 12px;">图3 线程池生命周期</span> </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><strong><span style="font-size: 18px;">2.3 任务执行机制</span></strong></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><strong><span style="font-size: 16px;">2.3.1 任务调度</span></strong></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">任务调度是线程池的主要入口,当用户提交了一个任务,接下来这个任务将如何执行都是由这个阶段决定的。了解这部分就相当于了解了线程池的核心运行机制。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">首先,所有任务的调度都是由execute方法完成的,这部分完成的工作是:检查现在线程池的运行状态、运行线程数、运行策略,决定接下来执行的流程,是直接申请线程执行,或是缓冲到队列中执行,亦或是直接拒绝该任务。其执行过程如下:</span></p> <ol class="list-paddingleft-2" style="list-style-type: decimal;"> <li style="font-size: 15px;"><p><span style="font-size: 15px;">首先检测线程池运行状态,如果不是RUNNING,则直接拒绝,线程池要保证在RUNNING的状态下执行任务。</span></p></li> <li style="font-size: 15px;"><p><span style="font-size: 15px;">如果workerCount < corePoolSize,则创建并启动一个线程来执行新提交的任务。</span></p></li> <li style="font-size: 15px;"><p><span style="font-size: 15px;">如果workerCount >= corePoolSize,且线程池内的阻塞队列未满,则将任务添加到该阻塞队列中。</span></p></li> <li style="font-size: 15px;"><p><span style="font-size: 15px;">如果workerCount >= corePoolSize && workerCount < maximumPoolSize,且线程池内的阻塞队列已满,则创建并启动一个线程来执行新提交的任务。</span></p></li> <li style="font-size: 15px;"><p><span style="font-size: 15px;">如果workerCount >= maximumPoolSize,并且线程池内的阻塞队列已满, 则根据拒绝策略来处理该任务, 默认的处理方式是直接抛异常。</span></p></li> </ol> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">其执行流程如下图所示:</span></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 0.5em;padding-right: 0.5em;"> <img data-ratio="0.898972602739726" src="/upload/b06a332965a66469ac512d92ff70e2db.png" data-type="png" data-w="584" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;width: 495px;height: 445px;" title="图4 任务调度流程"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> <span style="font-size: 12px;">图4 任务调度流程</span> </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><strong><span style="font-size: 16px;">2.3.2 任务缓冲</span></strong></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">任务缓冲模块是线程池能够管理任务的核心部分。线程池的本质是对任务和线程的管理,而做到这一点最关键的思想就是将任务和线程两者解耦,不让两者直接关联,才可以做后续的分配工作。线程池中是以生产者消费者模式,通过一个阻塞队列来实现的。阻塞队列缓存任务,工作线程从阻塞队列中获取任务。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">阻塞队列(</span><span style="font-size: 15px;color: rgb(136, 136, 136);">BlockingQueue</span><span style="font-size: 15px;">)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">下图中展示了线程1往阻塞队列中添加元素,而线程2从阻塞队列中移除元素:</span></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 0.5em;padding-right: 0.5em;"> <img data-ratio="0.31896551724137934" src="/upload/d95aaa14dc625aa364bb9383ed9dd53d.png" data-type="png" data-w="348" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;" title="图5 阻塞队列"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> <span style="font-size: 12px;">图5 阻塞队列</span> </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">使用不同的队列可以实现不一样的任务存取策略。在这里,我们可以再介绍下阻塞队列的成员:</span></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 0.5em;padding-right: 0.5em;"> <img data-cropselx1="0" data-cropselx2="546" data-cropsely1="0" data-cropsely2="246" data-ratio="0.4528301886792453" src="/upload/2a502a31771713d4f631034485b8b796.png" data-type="png" data-w="1378" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;width: 546px;height: 247px;" title=""> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><strong><span style="font-size: 16px;">2.3.3 任务申请</span></strong></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">由上文的任务分配部分可知,任务的执行有两种可能:一种是任务直接由新创建的线程执行。另一种是线程从任务队列中获取任务然后执行,执行完任务的空闲线程会再次去从队列中申请任务再去执行。第一种情况仅出现在线程初始创建的时候,第二种是线程获取任务绝大多数的情况。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">线程需要从任务缓存模块中不断地取任务执行,帮助线程从阻塞队列中获取任务,实现线程管理模块和任务管理模块之间的通信。这部分策略由getTask方法实现,其执行流程如下图所示:</span></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;padding-left: 0.5em;padding-right: 0.5em;"> <img data-cropselx1="2" data-cropselx2="459" data-cropsely1="0" data-cropsely2="396" data-ratio="0.859402460456942" src="/upload/88ce9b604268e9e98c455bbdbaa1fcd0.png" data-type="png" data-w="1138" style="font-size: inherit;color: inherit;line-height: inherit;display: block;margin-right: auto;margin-left: auto;width: 461px;height: 396px;" title="图6 获取任务流程图"> <figcaption style="line-height: inherit;margin-top: 10px;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;"> <span style="font-size: 12px;">图6 获取任务流程图</span> </figcaption> </figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">getTask这部分进行了多次判断,为的是控制线程的数量,使其符合线程池的状态。如果线程池现在不应该持有那么多线程,则会返回null值。工作线程Worker会不断接收新任务去执行,而当工作线程Worker接收不到任务的时候,就会开始被回收。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><strong><span style="font-size: 16px;">2.3.4 任务拒绝</span></strong></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">任务拒绝模块是线程池的保护部分,线程池有一个最大的容量,当线程池的任务缓存队列已满,并且线程池中的线程数目达到maximumPoolSize时,就需要拒绝掉该任务,采取任务拒绝策略,保护线程池。</span></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;padding-left: 0.5em;padding-right: 0.5em;"><span style="font-size: 15px;">拒绝策略是一个接口,其设计如下:</span></p> <p
作者:TheLast
public class VolatileCase { private static boolean ready; private static int number; private static class PrintThread extends Thread{ @Override public void run() { System.out.println("PrintThread is running......."); while(!ready); System.out.println("number = "+number); } } public static void main(String[] args) { new PrintThread().start(); SleepTools.second(1); number = 51; ready = true; SleepTools.second(5); System.out.println("main is ended!"); } } 这是我打印的结果 PrintThread is running....... number = 51 main is ended! 为什么不使用volatile,子线程依然能够知道ready变成了true呢。难道static也有可见性吗?请大家帮忙看看谢谢!
作者:微信小助手
<h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">概述</h2> <h3 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 22px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 30px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">什么是 Spring Boot?</h3> <p style="box-sizing: border-box;outline: 0px;margin-bottom: 16px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;font-size: 16px;color: rgb(77, 77, 77);line-height: 26px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。</p> <p><br></p> <p style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 22px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 30px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">Spring Boot 有哪些优点?</p> <p>Spring Boot 主要有如下优点:</p> <p><br></p> <ol class="list-paddingleft-2" style="list-style-type: decimal;"> <li><p>容易上手,提升开发效率,为 Spring 开发提供一个更快、更广泛的入门体验。</p></li> <li><p>开箱即用,远离繁琐的配置。</p></li> <li><p>提供了一系列大型项目通用的非业务性功能,例如:内嵌服务器、安全管理、运行数据监控、运行状况检查和外部化配置等。</p></li> <li><p>没有代码生成,也不需要XML配置。</p></li> <li><p>避免大量的 Maven 导入和各种版本冲突。</p></li> </ol> <p><br></p> <p><strong><span style="font-size: 24px;">Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?</span></strong></p> <p>启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:</p> <p><br></p> <p>启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:</p> <p><br></p> <p>@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。</p> <p><br></p> <p>@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能:@SpringBootApplication(exclude{DataSourceAutoConfiguration.class})</p> <p>@ComponentScan:Spring组件扫描。</p> <p><br></p> <h2 style="box-sizing: border-box;outline: 0px;margin-top: 8px;margin-bottom: 16px;font-size: 24px;font-family: "Microsoft YaHei", "SF Pro Display", Roboto, Noto, Arial, "PingFang SC", sans-serif;color: rgb(79, 79, 79);font-weight: 700;line-height: 32px;overflow-wrap: break-word;font-variant-ligatures: common-ligatures;text-align: start;white-space: normal;background-color: rgb(255, 255, 255);">配
作者:じ☆ve不哭
> 沉痛哀悼在对抗新冠肺炎疫情战斗中牺牲的烈士和逝世的同胞。 
作者:zzjj1988
目的:防止网站出现乱码,编写了一个过滤器EcondingFilter类来统一全站编码。我的疑问是:如果是以POST方式提交的数据,在代码里不会进入无限循坏吗?位置在代码里标记出来了。 public class EncodingFilter implements Filter { public void init(FilterConfig fileConfig) throws ServletException{ } public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throws IOException,ServletException { HttpServletRequest httpServletRequest=(HttpServletRequest) request; HttpServletRequest myRequest=new MyRequest(httpServletRequest); response.setContentType("text/html;charset=UTF-8"); chain.doFilter(myRequest, response); } public void destroy() { } } class MyRequest extends HttpServletRequestWrapper{ private HttpServletRequest request; private boolean hasEncode; public MyRequest (HttpServletRequest request) { super(request); this.request=request; } @Override public Map getParameterMap() { String method=request.getMethod(); if (method.equalsIgnoreCase("post")) { try { request.setCharacterEncoding("utf-8"); //如果是POST的方式,在下面代码处不会进入无限循坏吗? return request.getParameterMap(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }else if(method.equalsIgnoreCase("get")){ Map<String, String[]>parameterMap=request.getParameterMap(); if (!hasEncode) { for(String parameterName:parameterMap.keySet()) { String[] values=parameterMap.get(parameterName); if (values!=null) { for (int i = 0; i < values.length; i++) { try { values[i]=new String(values[i].getBytes("ios-8859-01"),"utf-8"); } catch (UnsupportedEncodingException e) { // TODO: handle exception e.printStackTrace(); } } } } hasEncode=true; } return parameterMap; } return super.getParameterMap(); } } }
作者:微信小助手
<section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="padding-top: 10px;padding-right: 10px;padding-left: 10px;background-color: rgb(239, 239, 239);box-sizing: border-box;"> <span style="display: inline-block;width: 5%;line-height: 0.8;font-weight: bolder;font-size: 48px;box-sizing: border-box;" title="" opera-tn-ra-cell="_$.pages:0.layers:0.comps:0.txt1"> <section style="box-sizing: border-box;"> “ </section></span> <section style="display: inline-block;vertical-align: top;float: right;width: 90%;line-height: 1.5;font-size: 15px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;">前段时间刚入职一家公司,就遇到了 MySQL 亿级大表优化这事!</span></p> </section> <section style="clear: both;box-sizing: border-box;line-height: 0;"> <section style="line-height: 0;width: 0px;"> <svg viewbox="0 0 1 1" style="vertical-align:top;"></svg> </section> </section> </section> </section> </section> <section style="line-height: 1.75em;"> <br> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;"> <img class="rich_pages" data-ratio="0.6734042553191489" data-s="300,640" src="/upload/43f12f01d0b990a99e010665552aec15.png" data-type="png" data-w="940" style=""> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 14px;letter-spacing: 1px;color: rgb(89, 89, 89);"><em>图片来自 Pexels</em></span> </section> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;border-top-color: rgb(89, 89, 89);border-right-color: rgb(89, 89, 89);border-left-color: rgb(89, 89, 89);font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">背景</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">XX 实例(一主一从)xxx 告警中每天凌晨在报 SLA 报警,该报警的意思是存在一定的主从延迟。(若在此时发生主从切换,需要长时间才可以完成切换,要追延迟来保证主从数据的一致性)</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">XX 实例的慢查询数量最多(执行时间超过 1s 的 SQL 会被记录),XX 应用那方每天晚上在做删除一个月前数据的任务。</span> </section> <section style="line-height: normal;"> <br> </section> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;border-top-color: rgb(89, 89, 89);border-right-color: rgb(89, 89, 89);border-left-color: rgb(89, 89, 89);font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">分析</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">使用 pt-query-digest 工具分析最近一周的 mysql-slow.log:</span></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: n
作者:微信小助手
<p style="text-align: center;"><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">(给</span><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;line-height: 22.4px;color: rgb(0, 128, 255);">ImportNew</span><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">加星标,提高Java技能)</span></p> <blockquote> <p><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">转自:博客园 作者:<span style="color: rgb(136, 134, 111);font-family: verdana, "ms song", Arial, Helvetica, sans-serif;font-size: 12px;text-align: left;background-color: rgb(250, 247, 239);"> </span></span><span style="font-size: 14px;">一点一滴的Beer </span></p> <p style="letter-spacing: 0.5440000295639038px;white-space: normal;background-color: rgb(255, 255, 255);max-width: 100%;min-height: 1em;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 14px;">www.cnblogs.com/beer/p/6029861.html</span></p> </blockquote> <h1 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">1 概述</span></strong></span></h1> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">在存在账号体系的信息系统中,对身份的鉴定是非常重要的事情。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">随着移动互联网时代到来,客户端的类型越来越多, 逐渐出现了 一个服务器,N个客户端的格局 。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><img data-ratio="1.0366379310344827" src="/upload/ada5da05b038cdef97c68b22be749835.png" data-type="png" data-w="464" data-backw="464" data-backh="481" style="width: 100%;height: auto;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;">不同的客户端产生了不同的用户使用场景,这些场景:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"> 1.有不同的环境安全威胁</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"> 2.不同的会话生存周期</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"> 3.不同的用户权限控制体系</span> </section> <section style="line-height: 1.5em;"> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"> 4.不同级别的接口调用方式</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">综上所述,它们的身份认证方式也存在一定的区别。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">本文将使用一定的篇幅对这些场景进行一些分析和梳理工作。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <h1 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">2 使用场景</span></strong></span></h1> <p><span style="font-size: 15px;letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">下面是一些在IT服务常见的一些使用场景:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"> 1.用户在web浏览器端登录系统,使用系统服务</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"> 2.用户在手机端(Android/iOS)登录系统,使用系统服务</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"> 3.用户使用开放接口登录系统,调用系统服务</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"> 4.用户在PC处理登录状态时通过手机扫码授权手机登录(使用得比较少)</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"> 5.用户在手机处理登录状态进通过手机扫码授权PC进行登录(比较常见)</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">通过对场景的细分,得到如下不同的认证token类别:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <p style="line-height: 1.5em;"><span style="font-size: 15px;letter-spacing: normal;"> 1. 原始账户密码类别</span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;letter-spacing: normal;"><br></span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"> 1.1用户名和密码</span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"> 1.2 API应用ID/KEY</span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"> 2.会话ID类别</span></p> <p style="line-height: 1.5em;"><br></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"> 2.1 浏览器端token</span></p> <p style="line-height: 1.5em;"><br></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"> 2.2 移动端token</span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"> 2.3 API应用token</span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"> 3. 接口调用类别</span></p> <p style="line-height: 1.5em;"><br></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"> 3.1 接口访问token</span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"> 3.2接口调用类别</span></p> <p style="line-height: 1.5em;"><br></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"> 4. 身份授权类别</span></p> <p style="line-height: 1.5em;"><br></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;"> 4.1 PC和移动端相互授权的token</span></p> <h1 style="line-height: 1.5em;"><br></h1> <h1 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">3 token的类别</span></strong></span></h1> <p><span style="font-size: 15px;letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">不同场景的token进行如下几个维度的对比:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">天然属性 对比:</span> </section> <p style="line-height: 1.5em;"><span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);">1.使用成本</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);"><br></span> </section> <section style="line-height: 1.5em;"> <span style="letter-spacing: normal;font-size: 15px;color: rgb(0, 0, 0);">本认证方式在使用的时候,造成的不便性。比如:</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 1.1 账号密码需要用户打开页面然后逐个键入</span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 1.2二维码需要用户掏出手机进行扫码操作</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;">2.变化成本</span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;">本认证方式,token发生变化时,用户需要做出的相应更改的成本:</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 2.1 用户名和密码发生变化时,用户需要额外记忆和重新键入新密码</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 2.2 API应用ID/KEY发生变化时,第三方应用需要重新在代码中修改并部署</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 2.3 授权二维码发生变化时,需要用户重新打开手机应用进行扫码</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;">3. 环境风险</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 3.1 被偷窥的风险</span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 3.2 被抓包的风险</span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 3.3 被伪造的风险</span> </section> <ol class="list-paddingleft-2"> <section style="line-height: 1.5em;"> <p style="line-height: 1.5em;"><br></p> </section> </ol> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">可调控属性 对比:</span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">1. 使用频率</span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"> 1.1 在网路中的传送频率</span><br></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;">2. 有效时间</span><br></p> <p style="line-height: 1.5em;"><br></p> <p style="line-height: 1.5em;"><span style="color: rgb(0, 0, 0);font-size: 15px;"> 2.1 此token从创建到终结的生存时间</span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">最终的目标:安全和影响。</span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">安全和隐私性主要体现在:</span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> 1. token 不容易被窃取和盗用(通过对传送频率控制)。</span></p> <p style="line-height: 1.5em;"><br></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> 2. token 即使被窃取,产生的影响也是可控的(通过对有效时间控制)。</span></p> <p style="line-height: 1.5em;"><br></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">关于隐私及隐私破坏后的后果,有如下的基本结论:</span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> 1. 曝光频率高的容易被截获</span></p> <p style="line-height: 1.5em;"><br></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> 2. 生存周期长的在被截获后产生的影响更严重和深远</span></p> <p style="line-height: 1.5em;"><br></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">遵守如下原则:</span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> 1. 变化成本高的token不要轻易变化</span></p> <p style="line-height: 1.5em;"><br></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> 2. 不轻易变化的token要减少曝光频率(网络传输次数)</span></p> <p style="line-height: 1.5em;"><br></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> 3. 曝光频率高的token的生存周期要尽量短</span></p> <p style="line-height: 1.5em;"><br></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">将各类token的固有特点及可控属性进行调控后, 对每个指标进行量化评分(1~5分),我们可以得到如下的对比表:</span></p> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><img data-ratio="0.47928176795580113" src="/upload/2a5f7c8c41bf891816721dabd753007f.png" data-type="png" data-w="724" data-backw="578" data-backh="277" style="width: 100%;height: auto;"></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">备注:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">user_name/passwd 和 app_id/app_key 是等价的效果。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h1 style="line-height: 1.5em;"><strong><span style="font-size: 15px;letter-spacing: normal;color: rgb(171, 25, 66);">4 token的层级关系</span></strong></h1> <p><strong><span style="font-size: 15px;letter-spacing: normal;color: rgb(171, 25, 66);"><br></span></strong></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">参考上一节的对比表,可以很容易对这些不同用途的token进行分层,主要可以分为4层:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 1. 密码层</span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 最传统的用户和系统之间约定的数字身份认证方式</span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 2. 会话层</span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 用户登录后的会话生命周期的会话认证</span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 3.调用层</span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 用户在会话期间对应用程序接口的调用认证</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 4.应用层</span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"> 用户获取了接口访问调用权限后的一些场景或者身份认证应用</span> </section> <ol class="list-paddingleft-2"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> </ol> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">token的分层图如下:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><img data-ratio="0.5186440677966102" src="/upload/85cc8f355eac13bf67f1248e4dd94ab9.png" data-type="png" data-w="590" data-backw="578" data-backh="300" style="width: 100%;height: auto;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">在一个多客户端的信息系统里面,这些token的产生及应用的内在联系如下:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <ol class="simple list-paddingleft-2"> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">用户输入用户名和用户口令进行一次性认证</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">在 不同 的终端里面生成拥有 不同 生命周期的会话token</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">客户端会话token从服务端交换生命周期短但曝光 频繁 的接口访问token</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">会话token可以生成和刷新延长 access_token 的生存时间</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section><p><br></p></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">access_token可以生成生存周期最短的用于授权的二维码的token</span> </section></li> </ol> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">使用如上的架构有如下的好处:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <ol class="simple list-paddingleft-2"> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">良好的统一性。可以解决不同平台上认证token的生存周期的 归一化问题</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">良好的解耦性。核心接口调用服务器的认证 access_token 可以完成独立的实现和</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">部署</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">良好的层次性。不同平台的可以有完全不同的用户权限控制系统,这个控制可以在 会话层 中各平台解决掉</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section></li> </ol> <h2 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">4.1 账号密码</span></strong></span></h2> <p><span style="font-size: 15px;letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">广义的 账号/密码 有如下的呈现方式:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <ol class="simple list-paddingleft-2"> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">传统的注册用户名和密码</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section><p><br></p></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">应用程序的app_id/app_key</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section></li> </ol> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">它们的特点如下:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <ol class="list-paddingleft-2"> <li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;">会有特别的意义</span> </section></li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">比如:用户自己为了方便记忆,会设置有一定含义的账号和密码。</span> </section> <section style="line-height: 1.5em;"> <br> </section> <li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;">不常修改</span> </section></li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">账号密码对用户有特别含义,一般没有特殊情况不会愿意修改。而app_id/app_key则会写在应用程序中,修改会意味着重新发布上线的成本</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;">一旦泄露影响深远</span> </section></li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">正因为不常修改,只要泄露了基本相当于用户的网络身份被泄露,而且只要没被察觉这种身份盗用就会一直存在</span> </section> </ol> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">所以在认证系统中应该尽量减少传输的机会,避免泄露。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <h2 style="line-height: 1.5em;"><strong><span style="font-size: 15px;letter-spacing: normal;color: rgb(171, 25, 66);">4.2 客户端会话token</span></strong></h2> <p><span style="font-size: 15px;letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">功能:充当着session的角色,不同的客户端有不同的生命周期。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">使用步骤:</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">用户使用账号密码,换取会话token。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">不同的平台的token有不同的特点。</span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <strong><span style="font-size: 15px;letter-spacing: normal;color: rgb(171, 25, 66);">Web平台生存周期短</span></strong> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">主要原因:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <ol class="list-paddingleft-2"> <li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;">环境安全性</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;"></span> </section></li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">由于web登录环境一般很可能是公共环境,被他人盗取的风险值较大</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;">输入便捷性</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;"></span> </section></li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">在PC上使用键盘输入会比较便捷</span> </section> <section style="line-height: 1.5em;"> <br> </section> </ol> <section style="line-height: 1.5em;"> <span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">移动端生存周期长</span></strong></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">主要原因:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <ol class="list-paddingleft-2"> <li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;">环境安全性</span> </section></li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">移动端平台是个人用户极其私密的平台,它人接触的机会不大</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;">输入便捷性</span> </section></li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">在移动端上使用手指在小屏幕上触摸输入体验差,输入成本高</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> </ol> <h2 style="line-height: 1.5em;"><br></h2> <h2 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">4.3 access_token</span></strong></span></h2> <p><span style="font-size: 15px;letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">功能:服务端应用程序api接口访问和调用的凭证。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">使用步骤:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">使用具有较长生命周期的会话token来换取此接口访问token。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">其曝光频率直接和接口调用频率有关,属于高频使用的凭证。为了照顾到隐私性,尽量减少其生命周期,即使被截取了,也不至于产生严重的后果。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">注意:在客户端token之下还加上一个access_token, 主要是为了让具有不同生命周期的客户端token最后在调用api的时候, 能够具有统一的认证方式。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <h2 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">4.4 pam_token</span></strong></span></h2> <p><span style="font-size: 15px;letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">功能:由已经登录和认证的PC端生成的二维码的原始串号(Pc Auth Mobile)。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;"></span> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">主要步骤如下:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <ol class="simple list-paddingleft-2"> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">PC上用户已经完成认证,登录了系统</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">PC端生成一组和此用户相关联的pam_token</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">PC端将此pam_token的使用链接生成二维码</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">移动端扫码后,请求服务器,并和用户信息关联</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">移动端获取refresh_token(长时效的会话)</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">根据 refresh_token 获取 access_token</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">完成正常的接口调用工作</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> </ol> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">备注:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">生存周期为2分钟,2分钟后过期删除。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">没有被使用时,每1分钟变一次。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">被使用后,立刻删除掉。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">此种认证模式一般不会被使用到。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"></span> </section> <h2 style="line-height: 1.5em;"><span style="font-size: 15px;letter-spacing: normal;"><br></span></h2> <h2 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">4.5 map_token</span></strong></span></h2> <p><span style="font-size: 15px;letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">功能:由已经登录的移动app来扫码认证PC端系统,并完成PC端系统的登录(Mobile Auth Pc)。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">主要步骤:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <ol class="simple list-paddingleft-2"> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">移动端完成用户身份的认证登录app</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">未登录的PC生成匿名的 map_token</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">移动端扫码后在db中生成 map_token 和用户关联(完成签名)</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">db同时针对此用户生成 web_token</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">PC端一直以 map_token 为参数查找此命名用户的 web_token</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">PC端根据 web_token 去获取 access_token</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">后续正常的调用接口调用工作</span> </section></li> </ol> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">备注:</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">生存周期为2分钟,2分钟后过期删除。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">没有被使用时,每1分钟变一次。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">被使用后,立刻删除掉。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <h1 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">5 小结与展望</span></strong></span></h1> <p><span style="font-size: 15px;letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">本文所设计的基于token的身份认证系统,主要解决了如下的问题:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <ol class="simple list-paddingleft-2"> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">token的分类问题</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">token的隐私性参数设置问题</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">token的使用场景问题</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">不同生命周期的token分层转化关系</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> </ol> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">本文中提到的设计方法,在 应用层 中可以适用于且不限于如下场景中:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section> <ol class="simple list-paddingleft-2"> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">用户登录</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">有时效的优惠券发放</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">有时效的邀请码发放</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">有时效的二维码授权</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">具有时效 手机/邮件 验证码</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">多个不同平台调用同一套API接口</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;"><br></span> </section></li> <li style="font-size: 15px;letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">多个平台使用同一个身份认证中心</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> </ol> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;">至于更多的使用场景,就需要大家去发掘了。</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section donone="shifuMouseDownCard('shifu_c_030')" label="Copyright Reserved by PLAYHUDONG." style="text-align: start;white-space: normal;margin-top: 1em;margin-bottom: 1em;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);border-width: 0px;border-style: initial;border-color: initial;"> <section style="margin-left: 1em;line-height: 1.4;"> <span style="padding: 3px 8px;border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;color: rgb(255, 255, 255);background-color: rgb(255, 105, 31);font-family: inherit;text-align: inherit;text-decoration: inherit;font-size: 16px;">推荐阅读</span> <span style="margin-left: 4px;padding: 3px 8px;border-top-left-radius: 1.2em;border-top-right-radius: 1.2em;border-bottom-right-radius: 1.2em;border-bottom-left-radius: 1.2em;color: rgb(255, 255, 255);line-height: 1.2;background-color: rgb(204, 204, 204);font-family: inherit;text-align: inherit;text-decoration: inherit;border-color: rgb(249, 110, 87);font-size: 12px;">点击标题可跳转</span> </section> <section style="margin-top: -11px;padding: 22px 16px 16px;border-width: 1px;border-style: solid;border-color: rgb(255, 105, 31);color: rgb(51, 51, 51);font-size: 1em;font-family: inherit;text-align: inherit;text-decoration: inherit;"> <p><span style="font-size: 12px;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-decoration: underline;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651486837&idx=2&sn=29fff05af3e40ebfd53b68e2e97ae727&chksm=bd25160a8a529f1c8b4594fc2a46fb9fa6b84e247b1afbd3dac56dadace5a244e530da532de3&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2">圣杯与银弹 · 没用的设计模式</a><br></span></p> <p><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-decoration: underline;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651486812&idx=1&sn=3d5778b3bf23a59e9141467ff9678f59&chksm=bd2516238a529f35a8a6818bec7f10b0353c7beeaf26d68e9da561209fba566f99314ed59c7a&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2">看完这篇 HTTPS ,和面试官扯皮就没问题了</a><br></span></p> <p><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-decoration: underline;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651486846&idx=1&sn=6800b03ef50e7ed81316e75cd6490d4f&chksm=bd2516018a529f17aef423d0adfe735cdec0e8fc511f01ad3af01c1cef156c1f2b2221c4eb11&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2">IDEA - 2020.1 版本针对调试器和代码分析器的改进,值得期待</a></span><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);"><br></span></p> </section> </section> <p style="caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);text-align: start;white-space: normal;"><br></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(255, 169, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">看完本文有收获?请转发分享给更多人</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;color: rgb(255, 169, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">关注「ImportNew」,提升Java技能</strong></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.9166666666666666" data-s="300,640" data-type="png" data-w="600" width="auto" src="/upload/899866149276fa5fddb73c61ae04be64.png" style="box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 600px !important;"></p> <p style="text-align: right;"><span style="font-size: 14px;text-align: right;">好文章,我</span><span style="font-size: 14px;text-align: right;color: rgb(255, 41, 65);">在看</span><span style="font-size: 14px;text-align: right;">❤️</span></p>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;padding-right: 10px;padding-left: 10px;word-break: break-word;overflow-wrap: break-word;text-align: left;margin-top: -10px;line-height: 1.75;color: rgb(89, 89, 89);font-family: Optima-Regular, Optima, PingFangTC-Light, PingFangSC-light, PingFangTC-light;letter-spacing: 2px;background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%);background-size: 20px 20px;background-position: center center;"> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(222, 198, 251);color: rgb(89, 89, 89);">定时任务简述</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">定时任务,在企业开发中尤其重要,很多业务都是需要定时任务去做的。比如说10点开售某件东西,凌晨0点统计注册人数,统计其他各种等等。这个时候不可能说让人为的去开启某个开关或者怎么怎么样的,如果这样的话,估计都要崩溃了。今天给大家介绍如何在项目中使用Quartz并且在后台动态配置定时任务的启动,暂停,重启,停止,还有修改启动的时间,修改执行的任务等。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(222, 198, 251);color: rgb(89, 89, 89);">引入依赖的jar包</span></h2> <section class="code-snippet__fix code-snippet__js"> <pre class="code-snippet__js hljs xml" data-lang="java"><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">dependency</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">groupId</span></span></span><span class="hljs-tag">></span></span>org.springframework.boot<span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">groupId</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">artifactId</span></span></span><span class="hljs-tag">></span></span>spring-boot-starter-quartz<span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">artifactId</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">dependency</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">dependency</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">groupId</span></span></span><span class="hljs-tag">></span></span>org.springframework.boot<span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">groupId</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">artifactId</span></span></span><span class="hljs-tag">></span></span>spring-boot-starter-web<span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">artifactId</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">dependency</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">dependency</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">groupId</span></span></span><span class="hljs-tag">></span></span>org.mybatis.spring.boot<span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">groupId</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">artifactId</span></span></span><span class="hljs-tag">></span></span>mybatis-spring-boot-starter<span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">artifactId</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">version</span></span></span><span class="hljs-tag">></span></span>1.3.2<span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">version</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">dependency</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">dependency</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">groupId</span></span></span><span class="hljs-tag">></span></span>mysql<span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">groupId</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">artifactId</span></span></span><span class="hljs-tag">></span></span>mysql-connector-java<span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">artifactId</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"><</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">scope</span></span></span><span class="hljs-tag">></span></span>runtime<span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">scope</span></span></span><span class="hljs-tag">></span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-tag"><span class="hljs-tag"></</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">dependency</span></span></span><span class="hljs-tag">></span></span></span></code></pre> </section> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(222, 198, 251);color: rgb(89, 89, 89);">application.yml的配置</span></h2> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <pre class="code-snippet__js hljs cpp" data-lang="yml"><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;">quartz:</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> scheduler:</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> instance-name: MyselfScheduler</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> instance-id: NON_CLUSTERED # 使用集群:AUTO 不使用集群:NON_CLUSTERED</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> skip-update-check: <span class="hljs-literal"><span class="hljs-literal">true</span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> job-factory:</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword">class</span></span></span><span class="hljs-class">:</span></span> org.quartz.simpl.SimpleJobFactory</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> job-store:</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword">class</span></span></span><span class="hljs-class">:</span></span> org.quartz.impl.jdbcjobstore.JobStoreTX</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> driver-delegate-<span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword">class</span></span></span><span class="hljs-class">:</span></span> org.quartz.impl.jdbcjobstore.StdJDBCDelegate</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource: quartzDataSource</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> table-prefix: QRTZ_</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> is-clustered: <span class="hljs-literal"><span class="hljs-literal">true</span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> thread-pool:</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword">class</span></span></span><span class="hljs-class">:</span></span> org.quartz.simpl.SimpleThreadPool</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> thread-count: <span class="hljs-number"><span class="hljs-number">5</span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource:</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> quartzDataSource:</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> driver: ${spring.datasource.druid.driver-<span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword">class</span></span></span><span class="hljs-class">-</span><span class="hljs-title"><span class="hljs-class"><span class="hljs-title">name</span></span></span><span class="hljs-class">}</span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"><span class="hljs-class"> <span class="hljs-title">url</span>:</span> ${spring.datasource.druid.url}</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> user: ${spring.datasource.druid.username}</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> password: ${spring.datasource.druid.password}</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> maxConnections: <span class="hljs-number"><span class="hljs-number">5</span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> validationQuery: select <span class="hljs-number"><span class="hljs-number">0</span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> connection-provider:</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-class"><span class="hljs-keyword"><span class="hljs-class"><span class="hljs-keyword">class</span></span></span><span class="hljs-class">:</span></span> com.lingdu.welend.config.quartz.DruidConnectionProvider</span></code></pre> </section> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(222, 198, 251);color: rgb(89, 89, 89);">扩展druid数据源作为quartz的数据源</span></h2> <section class="code-snippet__fix code-snippet__js"> <pre class="code-snippet__js hljs bash" data-lang="java"><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;">import com.alibaba.druid.pool.DruidDataSource;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;">import org.quartz.SchedulerException;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;">import org.quartz.utils.ConnectionProvider;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;">import java.sql.Connection;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;">import java.sql.SQLException;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;">/**</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> * @author Lee</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> * @// TODO 2018/6/1-16:37</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> * @description Druid连接池的Quartz扩展类</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> */</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;">public class DruidConnectionProvider implements ConnectionProvider {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> /*</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> * 常量配置,与quartz.properties文件的key保持一致(去掉前缀),同时提供<span class="hljs-built_in"><span class="hljs-built_in">set</span></span>方法,Quartz框架自动注入值。</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> */</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> //JDBC驱动</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public String driver;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> //JDBC连接串</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public String URL;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> //数据库用户名</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public String user;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> //数据库用户密码</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public String password;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> //数据库最大连接数</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public int maxConnections;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> //数据库SQL查询每次连接返回执行到连接池,以确保它仍然是有效的。</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public String validationQuery;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> private boolean validateOnCheckout;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> private int idleConnectionValidationSeconds;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public String maxCachedStatementsPerConnection;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> private String discardIdleConnectionsSeconds;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public static final int DEFAULT_DB_MAX_CONNECTIONS = 10;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public static final int DEFAULT_DB_MAX_CACHED_STATEMENTS_PER_CONNECTION = 120;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> //Druid连接池</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> private DruidDataSource datasource;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> /*</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> * 接口实现</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> */</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public Connection getConnection() throws SQLException {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-built_in"><span class="hljs-built_in">return</span></span> datasource.getConnection();</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public void shutdown() throws SQLException {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource.close();</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public void initialize() throws SQLException {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (this.URL == null) {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> throw new SQLException(<span class="hljs-string"><span class="hljs-string">"DBPool could not be created: DB URL cannot be null"</span></span>);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (this.driver == null) {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> throw new SQLException(<span class="hljs-string"><span class="hljs-string">"DBPool driver could not be created: DB driver class name cannot be null!"</span></span>);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (this.maxConnections < 0) {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> throw new SQLException(<span class="hljs-string"><span class="hljs-string">"DBPool maxConnectins could not be created: Max connections must be greater than zero!"</span></span>);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource = new DruidDataSource();</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> try {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource.setDriverClassName(this.driver);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> } catch (Exception e) {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> try {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> throw new SchedulerException(<span class="hljs-string"><span class="hljs-string">"Problem setting driver class name on datasource: "</span></span> + e.getMessage(), e);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> } catch (SchedulerException e1) {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource.setUrl(this.URL);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource.setUsername(this.user);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource.setPassword(this.password);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource.setMaxActive(this.maxConnections);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource.setMinIdle(1);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource.setMaxWait(0);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource.setMaxPoolPreparedStatementPerConnectionSize(DEFAULT_DB_MAX_CONNECTIONS);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (this.validationQuery != null) {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource.setValidationQuery(this.validationQuery);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (!this.validateOnCheckout)</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource.setTestOnReturn(<span class="hljs-literal"><span class="hljs-literal">true</span></span>);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-keyword"><span class="hljs-keyword">else</span></span></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource.setTestOnBorrow(<span class="hljs-literal"><span class="hljs-literal">true</span></span>);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> datasource.setValidationQueryTimeout(this.idleConnectionValidationSeconds);</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> /*</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> * 提供get <span class="hljs-built_in"><span class="hljs-built_in">set</span></span>方法</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> */</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public String <span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getDriver</span></span></span></span>() {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-built_in"><span class="hljs-built_in">return</span></span> driver;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public void setDriver(String driver) {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> this.driver = driver;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public String <span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getURL</span></span></span></span>() {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-built_in"><span class="hljs-built_in">return</span></span> URL;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public void setURL(String URL) {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> this.URL = URL;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public String <span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getUser</span></span></span></span>() {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-built_in"><span class="hljs-built_in">return</span></span> user;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public void setUser(String user) {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> this.user = user;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public String <span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getPassword</span></span></span></span>() {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-built_in"><span class="hljs-built_in">return</span></span> password;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public void setPassword(String password) {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> this.password = password;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public int <span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getMaxConnections</span></span></span></span>() {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-built_in"><span class="hljs-built_in">return</span></span> maxConnections;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public void setMaxConnections(int maxConnections) {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> this.maxConnections = maxConnections;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public String <span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getValidationQuery</span></span></span></span>() {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-built_in"><span class="hljs-built_in">return</span></span> validationQuery;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public void setValidationQuery(String validationQuery) {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> this.validationQuery = validationQuery;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public boolean <span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">isValidateOnCheckout</span></span></span></span>() {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-built_in"><span class="hljs-built_in">return</span></span> validateOnCheckout;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public void setValidateOnCheckout(boolean validateOnCheckout) {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> this.validateOnCheckout = validateOnCheckout;</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> }</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer"><br></span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> public int <span class="hljs-function"><span class="hljs-title"><span class="hljs-function"><span class="hljs-title">getIdleConnectionValidationSeconds</span></span></span></span>() {</span></code><code style=" border-radius: 0px;white-space: pre;display: flex; font-family: Consolas, "Liberation Mono" ,="" menlo,="" courier,="" monospace;="" "="" class="hljs"><span class="code-snippet_outer" style="line-height: 26px;"> <span class="hljs-built_in"><span class="hljs-built_in">return</span></span> idleConnectionValidationSeco