作者:微信小助手
<section style="margin-bottom: 0px;"> 你好,我叫拥抱拥抱硬核技术和对象,面向人民币编程的码哥。 </section> <section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-weui-theme="light" data-id="MzkzMDI1NjcyOQ==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/EoJib2tNvVtf7icAmS0BQH6oDVG37Q8NzcfdguS5qAqOhfxvZyIKqmuX5BbnDjynrBbZzktp1EiaeFLzapp1nHysw/0?wx_fmt=png" data-nickname="码哥字节" data-alias="MageByte" data-signature="拥抱硬核技术和对象,面向人民币编程。" data-from="0" data-is_biz_ban="0"></mp-common-profile> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;line-height: 1.6;word-spacing: 0px;letter-spacing: 0px;word-break: break-word;overflow-wrap: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;margin-bottom: 0px;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: #3f3f3f;font-size: 16px;margin: 10px 0px;">天有不测风云,数据库有旦夕祸福。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: #3f3f3f;font-size: 16px;margin: 10px 0px;">前面写 Redo 日志的文章介绍过,数据库正常运行时,Redo 日志就是个累赘。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: #3f3f3f;font-size: 16px;margin: 10px 0px;">现在,终于到了 Redo 日志扬眉吐气,大显身手的时候了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: #3f3f3f;font-size: 16px;margin: 10px 0px;">本文我们一起来看看,MySQL 在崩溃恢复过程中都干了哪些事情,Redo 日志又是怎么大显身手的。</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;display: block;font-size: 0.9em;overflow: auto;color: rgb(91, 91, 91);border-left: 3px solid rgb(158, 158, 158);background: rgba(158, 158, 158, 0.1);padding: 1px 0px 1px 10px;margin: 20px 0px;"> <p style="padding-top: 8px;padding-bottom: 8px;color: #3f3f3f;line-height: 1.5;font-size: 16px;margin: 10px;padding: 0px;">本文介绍的崩溃恢复过程,包含 <code style="word-wrap: break-word;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: #f8f5ec;color: #ff3502;line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">server 层</code>和 <code style="word-wrap: break-word;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: #f8f5ec;color: #ff3502;line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">InnoDB</code>,不涉及其它存储引擎,内容基于 <code style="word-wrap: break-word;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: #f8f5ec;color: #ff3502;line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">MySQL 8.0.29</code> 源码。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: #3f3f3f;font-size: 16px;margin: 10px 0px;"><strong style="font-weight: bold;color: #ff3502;line-height: 1.5;font-size: 16px;">目录</strong></p> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: disc;" class="list-paddingleft-1"> <li><p>1. 概述</p></li> <li><p>2. 读取两次写页面</p></li> <li><p>3. 恢复数据页</p></li> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: square;" class="list-paddingleft-1"> <li><p>3.1 找到 last_checkpoint_lsn</p></li> <li><p>3.2 修复损坏的数据页</p></li> <li><p>3.3 读取 Redo 日志</p></li> <li><p>3.4 应用 Redo 日志</p></li> </ul> <li><p>4. 删除 undo 表空间</p></li> <li><p>5. 初始化事务子系统</p></li> <li><p>6. 重建 undo 表空间</p></li> <li><p>7. 处理事务</p></li> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;list-style-type: square;" class="list-paddingleft-1"> <li><p>7.1 清理已提交事务</p></li> <li><p>7.2 回滚未提交 DDL 事务</p></li> <li><p>7.3 回滚未提交 DML 事务</p></li> <li><p>7.4 处理 PREPARE 事务</p></li> </ul> <li><p>8. 总结</p></li> </ul> <p><br></p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;margin: 80px 10px 40px 10px;text-align: center;font-weight: normal;color: #3f3f3f;font-size: 140%;">1. 概述</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: #3f3f3f;font-size: 16px;margin: 10px 0px;">MySQL 崩溃也是一次关闭过程,只是比正常关闭着急了一些。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: #3f3f3f;font-size: 16px;margin: 10px 0px;">正常关闭时,MySQL 会做一系列收尾工作,例如:清理 undo 日志、合并 change buffer 缓冲区等操作。</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;display: block;font-size: 0.9em;overflow: auto;color: rgb(91, 91, 91);border-left: 3px solid rgb(158, 158, 158);background: rgba(158, 158, 158, 0.1);padding:
作者:微信小助手
<p style="white-space: normal;margin-bottom: 0px;"><strong style="color: rgb(171, 25, 66);text-align: left;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;"><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;text-align: justify;letter-spacing: 0.034em;">一、好好的系统,为什么要分库分表?</span></strong></p> <p style="white-space: normal;margin-bottom: 0px;"><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;letter-spacing: 0.034em;"><br></span></p> <p style="white-space: normal;margin-bottom: 0px;"><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;letter-spacing: 0.034em;">还</span><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;letter-spacing: 0.034em;">是不着急实战,咱们先介绍下在分库分表架构实施过程中,会接触到的一些通用概念,了解这些概念能够帮助理解市面上其他的分库分表工具,尽管它们的实现方法可能存在差异,但整体思路基本一致。</span><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;letter-spacing: 0.034em;">因此,在开始实际操作之前,我们有必要先掌握这些通用概念,以便更好地理解和应用分库分表技术。</span></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;text-align: left;margin-bottom: 0px;"> <section style="white-space: normal;text-align: left;margin-bottom: 0px;"> <br> </section> <section style="white-space: normal;text-align: left;margin-bottom: 0px;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">我们结合具体业务场景,以 t_order 表为例进行架构优化。由于数据量已经达到亿级别,查询性能严重下降,因此我们采用了分库分表技术来处理这个问题。具体而言,我们将原本的单库分成了两个库,分别为 DB_1 和 DB_2,并在每个库中再次进行分表处理,生成 t_order_1 和 t_order_2 两张表,实现对订单表的分库分表处理。</span> </section> <p data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><br></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"></figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.5166666666666667" src="/upload/b87bdf61bb9452a059e136cb2c0cc52d.png" data-type="png" data-w="1080" style="white-space: normal;text-align: left;margin-bottom: 0px;"> </figure> <h2 data-tool="mdnice编辑器" style="whi
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" data-mpa-powered-by="yiban.io"> <p style="white-space: normal;margin-bottom: 0px;"><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;font-size: 15px;"></span><strong style="text-align: left;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;color: rgb(171, 25, 66);font-size: 16px;letter-spacing: 0.034em;"><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">一、深分页问题</span></strong><br></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;text-align: left;margin-bottom: 0px;"> <p><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></strong></span></p> <h2 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">1.1 创建表</span></strong></span></h2> <p><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></strong></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="sql"><code><span class="code-snippet_outer"><span class="code-snippet__keyword">CREATE</span> <span class="code-snippet__keyword">TABLE</span> <span class="code-snippet__string">`player`</span> (</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__string">`id`</span> <span class="code-snippet__built_in">bigint</span>(<span class="code-snippet__number">20</span>) <span class="code-snippet__keyword">NOT</span> <span class="code-snippet__literal">NULL</span> AUTO_INCREMENT <span class="code-snippet__keyword">COMMENT</span> <span class="code-snippet__string">'主键'</span>,</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__string">`player_id`</span> <span class="code-snippet__built_in">varchar</span>(<span class="code-snippet__number">256</span>) <span class="code-snippet__keyword">NOT</span> <span class="code-snippet__literal">NULL</span> <span class="code-snippet__keyword">COMMENT</span> <span class="code-snippet__string">'运动员编号'</span>,</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__string">`player_name`</span> <span class="code-snippet__built_in">varchar</span>(<span class="code-snippet__number">256</span>) <span class="code-snippet__keyword">NOT</span> <span class="code-snippet__literal">NULL</span> <span class="code-snippet__keyword">COMMENT</span> <span class="code-snippet__string">'运动员名称'</span>,</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__string">`height`</span> <span class="code-snippet__built_in">int</span>(<span class="code-snippet__number">11</span>) <span class="code-snippet__keyword">NOT</span> <span class="code-snippet__literal">NULL</span> <span class="code-snippet__keyword">COMMENT</span> <span class="code-snippet__string">'身高'</span>,</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__string">`weight`</span> <span class="code-snippet__built_in">int</span>(<span class="code-snippet__number">11</span>) <span class="code-snippet__keyword">NOT</span> <span class="code-snippet__literal">NULL</span> <span class="code-snippet__keyword">COMMENT</span> <span class="code-snippet__string">'体重'</span>,</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__string">`game_performance`</span> <span class="code-snippet__built_in">text</span> <span class="code-snippet__keyword">COMMENT</span> <span class="code-snippet__string">'最近一场比赛表现'</span>,</span></code><code><span class="code-snippet_outer"> PRIMARY <span class="code-snippet__keyword">KEY</span> (<span class="code-snippet__string">`id`</span>)</span></code><code><span class="code-snippet_outer">) <span class="code-snippet__keyword">ENGINE</span>=<span class="code-snippet__keyword">InnoDB</span> AUTO_INCREMENT=<span class="code-snippet__number">1</span> <span class="code-snippet__keyword">DEFAULT</span> <span class="code-snippet__keyword">CHARSET</span>=utf8</span></code></pre> </section> <section> <br> </section> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;text-align: left;margin-bottom: 0px;"> <h2 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">1.2 新增 100 万条数据</span></strong></span></h2> <p><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="java"><code><span class="code-snippet_outer"><span class="code-snippet__meta">@SpringBootTest</span>(classes = TestApplication.class)</span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">@RunWith</span>(SpringJUnit4ClassRunner.class)</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">public</span> <span class="code-snippet__class"><span class="code-snippet__keyword">class</span> <span class="code-snippet__title">PlayerServiceTest</span> </span>{</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__meta">@Resource</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">private</span> PlayerRepository playerRepository;</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__meta">@Test</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__function"><span class="code-snippet__keyword">public</span> <span class="code-snippet__keyword">void</span> <span class="code-snippet__title">initBigData</span><span class="code-snippet__params">()</span> </span>{</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">for</span> (<span class="code-snippet__keyword">int</span> i = <span class="code-snippet__number">0</span>; i < <span class="code-snippet__number">1000000</span>; i++) {</span></code><code><span class="code-snippet_outer"> PlayerEntity entity = <span class="code-snippet__keyword">new</span> PlayerEntity();</span></code><code><span class="code-snippet_outer"> entity.setPlayerId(UUID.randomUUID().toString());</span></code><code><span class="code-snippet_outer"> entity.setPlayerName(<span class="code-snippet__string">"球员_"</span> + System.currentTimeMillis());</span></code><code><span class="code-snippet_outer"> entity.setWeight(<span class="code-snippet__number">150</span>);</span></code><code><span class="code-snippet_outer"> entity.setHeight(<span class="code-snippet__number">188</span>);</span></code><code><span class="code-snippet_outer"> entity.setGamePerformance(<span class="code-snippet__string">"{\"runDistance\":8900.0,\"passSuccess\":80.12,\"scoreNum\":3}"</span>);</span></code><code><span class="code-snippet_outer"> playerRepository.insert(entity);</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer">}</span></code></pre> </section> <p style="white-space: normal;text-align: left;margin-bottom: 0px;"><br></p> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;text-align: left;margin-bottom: 0px;"> <h2 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">1.3 深分页语句</span></strong></h2> <p><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="sql"><code><span class="code-snippet_outer"><span class="code-snippet__keyword">select</span> * <span class="code-snippet__keyword">from</span> player <span class="code-snippet__keyword">limit</span> <span class="code-snippet__number">990000</span>,<span class="code-snippet__number">5</span></span></code></pre> </section> <p style="white-space: normal;margin-bottom: 0px;text-align: left;"><br></p> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;text-align: left;margin-bottom: 0px;"> <h2 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">1.4 结果分析</span></strong></h2> <p style="text-align: left;"><span style="font-size: 15px;"><br></span></p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="white-space: normal;margin-bottom: 0px;"> <li style="white-space: normal;margin-bottom: 0px;font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">查询耗时:1.233 秒</span> </section></li> <li style="white-space: normal;margin-bottom: 0px;font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">本语句目标查询 [990001 - 990005] 五条数据</span> </section></li> <li style="white-space: normal;margin-bottom: 0px;font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">但是执行时需要排序 [1-990005] 数据</span> </section></li> <li style="white-space: normal;margin-bottom: 0px;font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">丢弃 [1-990000] 只返回 [990001-990005]</span> </section></li> </ul> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;margin-bottom: 0px;"> <section style="white-space: normal;margin-bottom: 0px;"> <br> </section> <h1 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">二、深分页优化方案</span></strong></h1> <h2 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);"><br></span></strong></h2> <h2 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">2.1 方案一</span></strong></h2> <p data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><span style="font-size: 15px;">我们可以从业务形态维度去解决,可以参考搜索引擎解决方案。因为 ES 也存在深分页问题,搜索引擎解决方案是在业务上会限制查询页数。因为页数越大,内容相关度越低,所以页数太大对业务价值不高。MySQL可以类比处理:</span></p> <p data-tool="mdnice编辑器"><br></p> <ul class="list-paddingleft-1" style="list-style-type: disc;"> <li style="font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">限制查询页数</span> </section></li> <li style="font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">限制全量导出</span> </section></li> <li style="font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">查询时要求带必要条件(时间范围)</span> </section></li> </ul> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;"><br></span> </section> <h2 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">2.2 方案二</span></strong></h2> <h3 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><br></h3> <h3 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">2.2.1 优化语句</span></strong></h3> <p><span style="font-size: 15px;"><br></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="sql"><code><span class="code-snippet_outer"><span class="code-snippet__keyword">select</span> * <span class="code-snippet__keyword">from</span> player a, (<span class="code-snippet__keyword">select</span> <span class="code-snippet__keyword">id</span> <span class="code-snippet__keyword">as</span> tmpId <span class="code-snippet__keyword">from</span> player <span class="code-snippet__keyword">limit</span> <span class="code-snippet__number">990000</span>,<span class="code-snippet__number">5</span>) b <span class="code-snippet__keyword">WHERE</span> a.id = b.tmpId</span></code></pre> </section> <p><br></p> <h3 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">2.2.2 执行计划</span></strong></h3> <p style="white-space: normal;margin-bottom: 0px;text-align: left;"><br></p> <h4 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><strong><span style="font-size: 15px;">(1) 查看计划</span></strong><span style="font-size: 15px;"></span></h4> <p><span style="font-size: 15px;"><br></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="sql"><code><span class="code-snippet_outer"><span class="code-snippet__keyword">explain</span> <span class="code-snippet__keyword">select</span> * <span class="code-snippet__keyword">from</span> player a, (<span class="code-snippet__keyword">select</span> <span class="code-snippet__keyword">id</span> <span class="code-snippet__keyword">as</span> tmpId <span class="code-snippet__keyword">from</span> player <span class="code-snippet__keyword">limit</span> <span class="code-snippet__number">990000</span>,<span class="code-snippet__number">5</span>) b <span class="code-snippet__keyword">WHERE</span> a.id = b.tmpId</span></code></pre> </section> <p style="white-space: normal;margin-bottom: 0px;text-align: left;"><br></p> </section> <p style="white-space: normal;margin-bottom: 0px;text-align: left;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.2814814814814815" data-s="300,640" src="/upload/871dbf4cbbf6dff487da5c126d3fff59.jpg" data-type="jpeg" data-w="1080" style="letter-spacing: 0.034em;"><br></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;margin-bottom: 0px;text-align: left;"> <h4 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"></h4> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;margin-bottom: 0px;text-align: left;"> <h4 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><br></h4> <h4 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><strong><span style="font-size: 15px;">(2) 执行顺序</span></strong><span style="font-size: 15px;"></span></h4> <p><span style="font-size: 15px;"><br></span></p> <ul class="list-paddingleft-1" style="list-style-type: disc;"> <li style="font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">id 越大执行顺序越靠前</span> </section></li> <li style="font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">id 相同则按照行数从上到下执行</span> </section></li> </ul> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <br> </section> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;margin-bottom: 0px;text-align: left;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">本语句执行顺序如下图:</span> </section> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <br> </section> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;margin-bottom: 0px;text-align: left;"> <img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.25925925925925924" data-s="300,640" src="/upload/1b6db5d3a4e6a209d019bf7fa5d87435.jpg" data-type="jpeg" data-w="1080" style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <br> </section> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">第一步和第二步表示执行子查询,</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;">第三步表示 player 表与子查询关联。</span> </section> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com"> <br data-tool="mdnice编辑器" style="line-height: 1.6 !important;"> <h4 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><strong><span style="font-size: 15px;">(3) explain type</span></strong></h4> <h4 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><br></h4> <h4 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;">访问类型是重要分析指标:</h4> <p data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><span style="font-size: 15px;"><br></span></p> </section> <p style="white-space: normal;margin-bottom: 0px;text-align: left;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.7277777777777777" data-s="300,640" src="/upload/ecc90149e17fc3f2dbf9602b4a682844.jpg" data-type="jpeg" data-w="1080"></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;margin-bottom: 0px;text-align: left;"> <br data-tool="mdnice编辑器" style="line-height: 1.6 !important;"> <h4 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><strong><span style="font-size: 15px;">(4) explain Extra</span></strong><span style="font-size: 15px;"></span></h4> <p><span style="font-size: 15px;"><br></span></p> <p data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><span style="font-size: 15px;">Extra 表示执行计划扩展信息重点关注三个:</span></p> <p data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><span style="font-size: 15px;"><br></span></p> </section> <p style="white-space: normal;margin-bottom: 0px;text-align: left;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.27037037037037037" data-s="300,640" src="/upload/bf7f686ba8eb716da03d44ba11c9ad7c.jpg" data-type="jpeg" data-w="1080"></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;margin-bottom: 0px;text-align: left;"> <figure data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"> <figcaption style="white-space: normal;margin-bottom: 0px;text-align: left;"></figcaption> </figure> <br data-tool="mdnice编辑器" style="line-height: 1.6 !important;"> <h3 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">2.2.3 结果分析</span></strong></h3> <p><span style="font-size: 15px;"><br></span></p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="white-space: normal;margin-bottom: 0px;text-align: left;"> <li style="white-space: normal;margin-bottom: 0px;text-align: left;font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">查询耗时:0.5 秒</span> </section></li> <li style="white-space: normal;margin-bottom: 0px;text-align: left;font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">原因是覆盖索引提升查询效率(只查 ID 列)</span> </section></li> <li style="white-space: normal;margin-bottom: 0px;text-align: left;font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">覆盖索引是指查询时索引列完全包含查询列</span> </section></li> <li style="white-space: normal;margin-bottom: 0px;text-align: left;font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">using index 表示使用覆盖索引</span> </section></li> </ul> <br data-tool="mdnice编辑器" style="line-height: 1.6 !important;"> <h2 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">2.3 方案三</span></strong></h2> <p><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);"><br></span></strong></p> <h3 data-tool="mdnice编辑器" style="white-space: normal;text-align: left;margin-bottom: 0px;"><strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">2.3.1 优化语句</span></strong></h3> <p><span style="font-size: 15px;"><br></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="sql"><code><span class="code-snippet_outer"><span class="code-snippet__keyword">select</span> * <span class="code-snippet__keyword">from</span> player <span class="code-snippet__keyword">where</span> <span class="code-snippet__keyword">id</span> > <span class="code-snippet__number">990000</span> <span class="code-snippet__keyword">LIMIT</span> <span class="code-snippet__number">5</span></span></code></pre> </section> <p style="white-space: normal;margin-bottom: 0px;text-align: left;"><br></p> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;margin-bottom: 0px;text-align: left;"> <h3 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><strong><span style="font-size: 15px;">2.3.2 执行计划</span></strong><span style="font-size: 15px;"></span></h3> <p><span style="font-size: 15px;"><br></span></p> <h4 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><strong><span style="font-size: 15px;">(1) 查看计划</span></strong><span style="font-size: 15px;"></span></h4> <p><span style="font-size: 15px;"><br></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="sql"><code><span class="code-snippet_outer"><span class="code-snippet__keyword">explain</span> <span class="code-snippet__keyword">select</span> * <span class="code-snippet__keyword">from</span> player <span class="code-snippet__keyword">where</span> <span class="code-snippet__keyword">id</span> > <span class="code-snippet__number">990000</span> <span class="code-snippet__keyword">LIMIT</span> <span class="code-snippet__number">5</span></span></code></pre> </section> <p style="white-space: normal;margin-bottom: 0px;text-align: left;"><br></p> </section> <p style="white-space: normal;margin-bottom: 0px;text-align: left;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.21203703703703702" data-s="300,640" src="/upload/73ac2946bf287223a3eb021317296085.jpg" data-type="jpeg" data-w="1080" style="letter-spacing: 0.034em;"><br></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;margin-bottom: 0px;text-align: left;"> <h4 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><br></h4> <h4 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><strong><span style="font-size: 15px;">(2) 结果分析</span></strong><span style="font-size: 15px;"></span></h4> <p><span style="font-size: 15px;"><br></span></p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="white-space: normal;margin-bottom: 0px;text-align: left;"> <li style="white-space: normal;margin-bottom: 0px;text-align: left;font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">查询耗时:0.001 秒</span> </section></li> <li style="white-space: normal;margin-bottom: 0px;text-align: left;font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">range 表示索引范围搜索性能尚可</span> </section></li> </ul> <br data-tool="mdnice编辑器" style="line-height: 1.6 !important;"> <h4 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><strong><span style="font-size: 15px;">(3) 适用场景</span></strong><span style="font-size: 15px;"></span></h4> <p><span style="font-size: 15px;"><br></span></p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="white-space: normal;margin-bottom: 0px;text-align: left;"> <li style="white-space: normal;margin-bottom: 0px;text-align: left;font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">不适用跳页场景</span> </section></li> <li style="white-space: normal;margin-bottom: 0px;text-align: left;font-size: 15px;"> <section style="white-space: normal;margin-bottom: 0px;text-align: left;"> <span style="font-size: 15px;">只适用【上一页】【下一页】场景</span> </section></li> </ul> <br data-tool="mdnice编辑器" style="line-height: 1.6 !important;"> <h1 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;">三、MyBatis</span></strong></span><span style="font-size: 15px;"></span></h1> <p><span style="font-size: 15px;"><br></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="xml"><code><span class="code-snippet_outer"><span class="code-snippet__tag"><<span class="code-snippet__name">mapper</span> <span class="code-snippet__attr">namespace</span>=<span class="code-snippet__string">"com.test.java.front.test.mysql.deep.page.repository.PlayerRepository"</span>></span></span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">resultMap</span> <span class="code-snippet__attr">id</span>=<span class="code-snippet__string">"BaseResultMap"</span> <span class="code-snippet__attr">type</span>=<span class="code-snippet__string">"com.test.java.front.test.mysql.deep.page.entity.PlayerEntity"</span>></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">id</span> <span class="code-snippet__attr">column</span>=<span class="code-snippet__string">"id"</span> <span class="code-snippet__attr">jdbcType</span>=<span class="code-snippet__string">"BIGINT"</span> <span class="code-snippet__attr">property</span>=<span class="code-snippet__string">"id"</span> /></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">result</span> <span class="code-snippet__attr">column</span>=<span class="code-snippet__string">"player_id"</span> <span class="code-snippet__attr">jdbcType</span>=<span class="code-snippet__string">"VARCHAR"</span> <span class="code-snippet__attr">property</span>=<span class="code-snippet__string">"playerId"</span> /></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">result</span> <span class="code-snippet__attr">column</span>=<span class="code-snippet__string">"player_name"</span> <span class="code-snippet__attr">jdbcType</span>=<span class="code-snippet__string">"VARCHAR"</span> <span class="code-snippet__attr">property</span>=<span class="code-snippet__string">"playerName"</span> /></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">result</span> <span class="code-snippet__attr">column</span>=<span class="code-snippet__string">"height"</span> <span class="code-snippet__attr">jdbcType</span>=<span class="code-snippet__string">"INTEGER"</span> <span class="code-snippet__attr">property</span>=<span class="code-snippet__string">"height"</span> /></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">result</span> <span class="code-snippet__attr">column</span>=<span class="code-snippet__string">"weight"</span> <span class="code-snippet__attr">jdbcType</span>=<span class="code-snippet__string">"INTEGER"</span> <span class="code-snippet__attr">property</span>=<span class="code-snippet__string">"weight"</span> /></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">result</span> <span class="code-snippet__attr">column</span>=<span class="code-snippet__string">"game_performance"</span> <span class="code-snippet__attr">jdbcType</span>=<span class="code-snippet__string">"LONGVARCHAR"</span> <span class="code-snippet__attr">property</span>=<span class="code-snippet__string">"gamePerformance"</span> /></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"></<span class="code-snippet__name">resultMap</span>></span></span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">sql</span> <span class="code-snippet__attr">id</span>=<span class="code-snippet__string">"Base_Column_List"</span>></span></span></code><code><span class="code-snippet_outer"> id, player_id, player_name, height, weight, game_performance</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"></<span class="code-snippet__name">sql</span>></span></span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">sql</span> <span class="code-snippet__attr">id</span>=<span class="code-snippet__string">"conditions"</span>></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">where</span>></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">if</span> <span class="code-snippet__attr">test</span>=<span class="code-snippet__string">"playerId != null"</span>></span></span></code><code><span class="code-snippet_outer"> and player_id = #{playerId,jdbcType=VARCHAR}</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"></<span class="code-snippet__name">if</span>></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"></<span class="code-snippet__name">where</span>></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"></<span class="code-snippet__name">sql</span>></span></span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">sql</span> <span class="code-snippet__attr">id</span>=<span class="code-snippet__string">"pager"</span>></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">if</span> <span class="code-snippet__attr">test</span>=<span class="code-snippet__string">"skip != null and limit != null"</span>></span></span></code><code><span class="code-snippet_outer"> limit #{skip}, #{limit}</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"></<span class="code-snippet__name">if</span>></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"></<span class="code-snippet__name">sql</span>></span></span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment"><!-- 查询条数 --></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">select</span> <span class="code-snippet__attr">id</span>=<span class="code-snippet__string">"selectPageCount"</span> <span class="code-snippet__attr">parameterType</span>=<span class="code-snippet__string">"com.test.java.front.test.mysql.deep.page.param.biz.PlayerQueryParam"</span> <span class="code-snippet__attr">resultType</span>=<span class="code-snippet__string">"java.lang.Long"</span>></span></span></code><code><span class="code-snippet_outer"> select count(*) from player</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">include</span> <span class="code-snippet__attr">refid</span>=<span class="code-snippet__string">"conditions"</span> /></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"></<span class="code-snippet__name">select</span>></span></span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment"><!-- 分页方式1:普通分页存在深分页问题 --></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment"><!-- select * from player limit 990000,5 --></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">select</span> <span class="code-snippet__attr">id</span>=<span class="code-snippet__string">"selectPager1"</span> <span class="code-snippet__attr">parameterType</span>=<span class="code-snippet__string">"com.test.java.front.test.mysql.deep.page.param.biz.PlayerQueryParam"</span> <span class="code-snippet__attr">resultMap</span>=<span class="code-snippet__string">"BaseResultMap"</span>></span></span></code><code><span class="code-snippet_outer"> select</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">include</span> <span class="code-snippet__attr">refid</span>=<span class="code-snippet__string">"Base_Column_List"</span> /></span></span></code><code><span class="code-snippet_outer"> from player</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">include</span> <span class="code-snippet__attr">refid</span>=<span class="code-snippet__string">"conditions"</span> /></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">include</span> <span class="code-snippet__attr">refid</span>=<span class="code-snippet__string">"pager"</span> /></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"></<span class="code-snippet__name">select</span>></span></span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment"><!-- 分页方式2:覆盖索引优化深分页问题 --></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment"><!-- select * from player a, (select id as tmpId from player limit 990000,5) b where a.id = b.tmpId --></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">select</span> <span class="code-snippet__attr">id</span>=<span class="code-snippet__string">"selectPager2"</span> <span class="code-snippet__attr">parameterType</span>=<span class="code-snippet__string">"com.test.java.front.test.mysql.deep.page.param.biz.PlayerQueryParam"</span> <span class="code-snippet__attr">resultMap</span>=<span class="code-snippet__string">"BaseResultMap"</span>></span></span></code><code><span class="code-snippet_outer"> select</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">include</span> <span class="code-snippet__attr">refid</span>=<span class="code-snippet__string">"Base_Column_List"</span> /></span></span></code><code><span class="code-snippet_outer"> from player a,</span></code><code><span class="code-snippet_outer"> (</span></code><code><span class="code-snippet_outer"> select id as tmpId from player</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">include</span> <span class="code-snippet__attr">refid</span>=<span class="code-snippet__string">"conditions"</span> /></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">include</span> <span class="code-snippet__attr">refid</span>=<span class="code-snippet__string">"pager"</span> /></span></span></code><code><span class="code-snippet_outer"> ) b</span></code><code><span class="code-snippet_outer"> where a.id = b.tmpId</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"></<span class="code-snippet__name">select</span>></span></span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment"><!-- 分页方式3:Id分页不支持跳页 --></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment"><!-- select * from player where id > 990000 limit 5 --></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">select</span> <span class="code-snippet__attr">id</span>=<span class="code-snippet__string">"selectPager3"</span> <span class="code-snippet__attr">parameterType</span>=<span class="code-snippet__string">"com.test.java.front.test.mysql.deep.page.param.biz.PlayerQueryIdParam"</span> <span class="code-snippet__attr">resultMap</span>=<span class="code-snippet__string">"BaseResultMap"</span>></span></span></code><code><span class="code-snippet_outer"> select</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">include</span> <span class="code-snippet__attr">refid</span>=<span class="code-snippet__string">"Base_Column_List"</span> /></span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"><<span class="code-snippet__name">include</span> <span class="code-snippet__attr">refid</span>=<span class="code-snippet__string">"conditions"</span> /></span></span></code><code><span class="code-snippet_outer"> from player where id > #{startId} limit #{pageSize}</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__tag"></<span class="code-snippet__name">select</span>></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__tag"></<span class="code-snippet__name">mapper</span>></span></span></code></pre> </section> <p style="white-space: normal;margin-bottom: 0px;text-align: left;"><br></p> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;margin-bottom: 0px;text-align: left;"> <h1 data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><strong><span style="font-size: 15px;color: rgb(171, 25, 66);">总结</span></strong><span style="font-size: 15px;"></span></h1> <p data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><br></p> <p data-tool="mdnice编辑器" style="white-space: normal;margin-bottom: 0px;text-align: left;"><span style="font-size: 15px;">本文首先介绍深分页问题表现和原因,然后介绍深分页问题三种解决方法,方案一从业务维度优化,方案二使用覆盖索引进行优化,方案三使用 ID 分页。最后展示了 MyBatis 相关代码。</span></p> </section> </section>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;overflow-wrap: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;"> <h3 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;font-size: 20px;margin-top: 0px;">引言<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">对于刚开始接触互联网开发的时候,在我们的固有印象是前端的请求直接到达后端,后端进行业务逻辑处理,然后将处理的结果返回前端,前端进行展示,最后整个过程就结束啦。</p> <p style="text-align: center;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.30604982206405695" data-s="300,640" src="/upload/9b81ff0b63b7b595dbc74afebe688eb6.png" data-type="png" data-w="562" style=""></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">虽然具体的业务逻辑是在<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">web</code>后端进行处理的,但是在前后端交互的时候,两者之间是存在一整个链路。真正的一个系统并不是只有前端和后端组成,它们只是这个系统的最前和最后的两个点,在之间还有很多服务发挥着作用。比如阿里云的<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">SLB(Server load Balance)</code>服务,为系统提供可靠的服务起到至关重要的作用、比如<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">kong</code>起着鉴权的作用。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>常见的交互链路<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">给出一张实际的前后端交互链路。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <p style="text-align: center;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.49859681945743684" data-s="300,640" src="/upload/bc6bdf0b1e54f37b231f68c41ab94974.png" data-type="png" data-w="1069" style=""></p> <figcaption style="margin-top: 5px;text-align: center;color: #888;font-size: 14px;"> <br> </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">在这张图中可以看到,真正的后端服务是包围在内网之中,并且组成也很复杂,除了处理业务的服务<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">1</code>、<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">2</code>外,还有<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">kong</code>网关、<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">k8s</code>集群。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">在整个后端服务中,通过网关暴露出唯一入口,当<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">app</code>或者第三方服务要访问后端服务<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">1</code>或者<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">2</code>时,只能先访问<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">kong</code>网关。在<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">kong</code>网关这里可以进行鉴权操作,只有校验通过的请求才能进入下一步。现在很多后端项目都进行了上云操作,使用<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">k8s</code>去管理服务,对此所有的服务都可集群到一个<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">k8s</code>服务中,在<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">k8s</code>集群中的服务之间通过<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">Feign</code>调用,以注解的方式实现服务之间的调用,非常的方便。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>结语<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">以上就是一个简单的后端交互链路,较为简单。分享一个较为复杂和全面的交互链路图。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <p style="text-align: center;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.6787037037037037" data-s="300,640" src="/upload/b081f289e10fe3cb0a12401bcd6ff920.png" data-type="png" data-w="1080" style=""></p> <figcaption style="margin-top: 5px;text-align: center;color: #888;font-size: 14px;"> <br> </figcaption> </figure> </section> <p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p>
作者:微信小助手
<h2 data-tool="mdnice编辑器" style="margin-top: 1em;margin-bottom: 0rem;padding-top: 0.5em;padding-bottom: 0.5em;outline: 0px;font-weight: bold;font-size: 23px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 32px;color: rgb(53, 179, 120);display: inline-block;border-bottom: 0px solid rgb(53, 179, 120);border-top-color: rgb(53, 179, 120);border-right-color: rgb(53, 179, 120);border-left-color: rgb(53, 179, 120);visibility: visible;">断言</h2> <ol data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;visibility: visible;"> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 10px;margin-bottom: 10px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 断言是一个逻辑判断,用于检查不应该发生的情况 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 10px;margin-bottom: 10px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> Assert 关键字在 JDK1.4 中引入,可通过 JVM 参数 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 179, 120);visibility: visible;">-enableassertions</code>开启 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 10px;margin-bottom: 10px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> SpringBoot 中提供了 Assert 断言工具类,通常用于数据合法性检查 </section></li> </ol> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;visibility: visible;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;visibility: visible;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;visibility: visible;">// 要求参数 object 必须为非空(Not Null),否则抛出异常,不予放行<br style="outline: 0px;visibility: visible;">// 参数 message 参数用于定制异常信息。<br style="outline: 0px;visibility: visible;">void notNull(Object object, String message)<br style="outline: 0px;visibility: visible;">// 要求参数必须空(Null),否则抛出异常,不予『放行』。<br style="outline: 0px;visibility: visible;">// 和 notNull() 方法断言规则相反<br style="outline: 0px;visibility: visible;">void isNull(Object object, String message)<br style="outline: 0px;visibility: visible;">// 要求参数必须为真(True),否则抛出异常,不予『放行』。<br style="outline: 0px;">void isTrue(boolean expression, String message)<br style="outline: 0px;">// 要求参数(List/Set)必须非空(Not Empty),否则抛出异常,不予放行<br style="outline: 0px;">void notEmpty(Collection collection, String message)<br style="outline: 0px;">// 要求参数(String)必须有长度(即,Not Empty),否则抛出异常,不予放行<br style="outline: 0px;">void hasLength(String text, String message)<br style="outline: 0px;">// 要求参数(String)必须有内容(即,Not Blank),否则抛出异常,不予放行<br style="outline: 0px;">void hasText(String text, String message)<br style="outline: 0px;">// 要求参数是指定类型的实例,否则抛出异常,不予放行<br style="outline: 0px;">void isInstanceOf(Class <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">type</span>, Object obj, String message)<br style="outline: 0px;">// 要求参数 `subType` 必须是参数 superType 的子类或实现类,否则抛出异常,不予放行<br style="outline: 0px;">void isAssignable(Class superType, Class subType, String message)<br style="outline: 0px;"></code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 1em;margin-bottom: 0rem;padding-top: 0.5em;padding-bottom: 0.5em;outline: 0px;font-weight: bold;font-size: 23px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 32px;color: rgb(53, 179, 120);display: inline-block;border-bottom: 0px solid rgb(53, 179, 120);border-top-color: rgb(53, 179, 120);border-right-color: rgb(53, 179, 120);border-left-color: rgb(53, 179, 120);">对象、数组、集合</h2> <h3 data-tool="mdnice编辑器" style="margin-top: 1.2em;margin-bottom: 1em;outline: 0px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(53, 179, 120);">ObjectUtils</h3> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">获取对象的基本信息</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 获取对象的类名。参数为 null 时,返回字符串:<span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">"null"</span> <br style="outline: 0px;">String nullSafeClassName(Object obj)<br style="outline: 0px;">// 参数为 null 时,返回 0<br style="outline: 0px;">int nullSafeHashCode(Object object)<br style="outline: 0px;">// 参数为 null 时,返回字符串:<span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">"null"</span><br style="outline: 0px;">String nullSafeToString(boolean[] array)<br style="outline: 0px;">// 获取对象 HashCode(十六进制形式字符串)。参数为 null 时,返回 0 <br style="outline: 0px;">String getIdentityHexString(Object obj)<br style="outline: 0px;">// 获取对象的类名和 HashCode。 参数为 null 时,返回字符串:<span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">""</span> <br style="outline: 0px;">String identityToString(Object obj)<br style="outline: 0px;">// 相当于 toString()方法,但参数为 null 时,返回字符串:<span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">""</span><br style="outline: 0px;">String getDisplayString(Object obj)<br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">判断工具</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 判断数组是否为空<br style="outline: 0px;">boolean isEmpty(Object[] array)<br style="outline: 0px;">// 判断参数对象是否是数组<br style="outline: 0px;">boolean isArray(Object obj)<br style="outline: 0px;">// 判断数组中是否包含指定元素<br style="outline: 0px;">boolean containsElement(Object[] array, Object element)<br style="outline: 0px;">// 相等,或同为 null时,返回 <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">true</span><br style="outline: 0px;">boolean nullSafeEquals(Object o1, Object o2)<br style="outline: 0px;">/*<br style="outline: 0px;">判断参数对象是否为空,判断标准为:<br style="outline: 0px;"> Optional: Optional.empty()<br style="outline: 0px;"> Array: length == 0<br style="outline: 0px;">CharSequence: length == 0<br style="outline: 0px;"> Collection: Collection.isEmpty()<br style="outline: 0px;"> Map: Map.isEmpty()<br style="outline: 0px;"> */<br style="outline: 0px;">boolean isEmpty(Object obj)<br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">其他工具方法</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 向参数数组的末尾追加新元素,并返回一个新数组<br style="outline: 0px;"><A, O extends A> A[] addObjectToArray(A[] array, O obj)<br style="outline: 0px;">// 原生基础类型数组 --> 包装类数组<br style="outline: 0px;">Object[] toObjectArray(Object <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">source</span>)<br style="outline: 0px;"></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 1.2em;margin-bottom: 1em;outline: 0px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(53, 179, 120);">StringUtils</h3> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">字符串判断工具</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 判断字符串是否为 null,或 <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">""</span>。注意,包含空白符的字符串为非空<br style="outline: 0px;">boolean isEmpty(Object str)<br style="outline: 0px;">// 判断字符串是否是以指定内容结束。忽略大小写<br style="outline: 0px;">boolean endsWithIgnoreCase(String str, String suffix)<br style="outline: 0px;">// 判断字符串是否已指定内容开头。忽略大小写<br style="outline: 0px;">boolean startsWithIgnoreCase(String str, String prefix) <br style="outline: 0px;">// 是否包含空白符<br style="outline: 0px;">boolean containsWhitespace(String str)<br style="outline: 0px;">// 判断字符串非空且长度不为 0,即,Not Empty<br style="outline: 0px;">boolean hasLength(CharSequence str)<br style="outline: 0px;">// 判断字符串是否包含实际内容,即非仅包含空白符,也就是 Not Blank<br style="outline: 0px;">boolean hasText(CharSequence str)<br style="outline: 0px;">// 判断字符串指定索引处是否包含一个子串。<br style="outline: 0px;">boolean substringMatch(CharSequence str, int index, CharSequence substring)<br style="outline: 0px;">// 计算一个字符串中指定子串的出现次数<br style="outline: 0px;">int countOccurrencesOf(String str, String sub)<br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">字符串操作工具</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 查找并替换指定子串<br style="outline: 0px;">String replace(String inString, String oldPattern, String newPattern)<br style="outline: 0px;">// 去除尾部的特定字符<br style="outline: 0px;">String trimTrailingCharacter(String str, char trailingCharacter) <br style="outline: 0px;">// 去除头部的特定字符<br style="outline: 0px;">String trimLeadingCharacter(String str, char leadingCharacter)<br style="outline: 0px;">// 去除头部的空白符<br style="outline: 0px;">String trimLeadingWhitespace(String str)<br style="outline: 0px;">// 去除头部的空白符<br style="outline: 0px;">String trimTrailingWhitespace(String str)<br style="outline: 0px;">// 去除头部和尾部的空白符<br style="outline: 0px;">String trimWhitespace(String str)<br style="outline: 0px;">// 删除开头、结尾和中间的空白符<br style="outline: 0px;">String trimAllWhitespace(String str)<br style="outline: 0px;">// 删除指定子串<br style="outline: 0px;">String delete(String inString, String pattern)<br style="outline: 0px;">// 删除指定字符(可以是多个)<br style="outline: 0px;">String deleteAny(String inString, String charsToDelete)<br style="outline: 0px;">// 对数组的每一项执行 trim() 方法<br style="outline: 0px;">String[] trimArrayElements(String[] array)<br style="outline: 0px;">// 将 URL 字符串进行解码<br style="outline: 0px;">String uriDecode(String <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">source</span>, Charset charset)<br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">路径相关工具方法</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 解析路径字符串,优化其中的 “..” <br style="outline: 0px;">String cleanPath(String path)<br style="outline: 0px;">// 解析路径字符串,解析出文件名部分<br style="outline: 0px;">String getFilename(String path)<br style="outline: 0px;">// 解析路径字符串,解析出文件后缀名<br style="outline: 0px;">String getFilenameExtension(String path)<br style="outline: 0px;">// 比较两个两个字符串,判断是否是同一个路径。会自动处理路径中的 “..” <br style="outline: 0px;">boolean pathEquals(String path1, String path2)<br style="outline: 0px;">// 删除文件路径名中的后缀部分<br style="outline: 0px;">String stripFilenameExtension(String path) <br style="outline: 0px;">// 以 “. 作为分隔符,获取其最后一部分<br style="outline: 0px;">String unqualify(String qualifiedName)<br style="outline: 0px;">// 以指定字符作为分隔符,获取其最后一部分<br style="outline: 0px;">String unqualify(String qualifiedName, char separator)<br style="outline: 0px;"></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 1.2em;margin-bottom: 1em;outline: 0px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(53, 179, 120);">CollectionUtils</h3> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">集合判断工具</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 判断 List/Set 是否为空<br style="outline: 0px;">boolean isEmpty(Collection<?> collection)<br style="outline: 0px;">// 判断 Map 是否为空<br style="outline: 0px;">boolean isEmpty(Map<?,?> map)<br style="outline: 0px;">// 判断 List/Set 中是否包含某个对象<br style="outline: 0px;">boolean containsInstance(Collection<?> collection, Object element)<br style="outline: 0px;">// 以迭代器的方式,判断 List/Set 中是否包含某个对象<br style="outline: 0px;">boolean contains(Iterator<?> iterator, Object element)<br style="outline: 0px;">// 判断 List/Set 是否包含某些对象中的任意一个<br style="outline: 0px;">boolean containsAny(Collection<?> <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">source</span>, Collection<?> candidates)<br style="outline: 0px;">// 判断 List/Set 中的每个元素是否唯一。即 List/Set 中不存在重复元素<br style="outline: 0px;">boolean hasUniqueObject(Collection<?> collection)<br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">集合操作工具</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 将 Array 中的元素都添加到 List/Set 中<br style="outline: 0px;"><E> void mergeArrayIntoCollection(Object array, Collection<E> collection) <br style="outline: 0px;">// 将 Properties 中的键值对都添加到 Map 中<br style="outline: 0px;"><K,V> void mergePropertiesIntoMap(Properties props, Map<K,V> map)<br style="outline: 0px;">// 返回 List 中最后一个元素<br style="outline: 0px;"><T> T lastElement(List<T> list) <br style="outline: 0px;">// 返回 Set 中最后一个元素<br style="outline: 0px;"><T> T lastElement(Set<T> <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">set</span>) <br style="outline: 0px;">// 返回参数 candidates 中第一个存在于参数 <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">source</span> 中的元素<br style="outline: 0px;"><E> E findFirstMatch(Collection<?> <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">source</span>, Collection<E> candidates)<br style="outline: 0px;">// 返回 List/Set 中指定类型的元素。<br style="outline: 0px;"><T> T findValueOfType(Collection<?> collection, Class<T> <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">type</span>)<br style="outline: 0px;">// 返回 List/Set 中指定类型的元素。如果第一种类型未找到,则查找第二种类型,以此类推<br style="outline: 0px;">Object findValueOfType(Collection<?> collection, Class<?>[] types)<br style="outline: 0px;">// 返回 List/Set 中元素的类型<br style="outline: 0px;">Class<?> findCommonElementType(Collection<?> collection)<br style="outline: 0px;"></code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 1em;margin-bottom: 0rem;padding-top: 0.5em;padding-bottom: 0.5em;outline: 0px;font-weight: bold;font-size: 23px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 32px;color: rgb(53, 179, 120);display: inline-block;border-bottom: 0px solid rgb(53, 179, 120);border-top-color: rgb(53, 179, 120);border-right-color: rgb(53, 179, 120);border-left-color: rgb(53, 179, 120);">文件、资源、IO 流</h2> <h3 data-tool="mdnice编辑器" style="margin-top: 1.2em;margin-bottom: 1em;outline: 0px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(53, 179, 120);">FileCopyUtils</h3> <ol data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: black;"> <li style="outline: 0px;"> <section style="margin-top: 10px;margin-bottom: 10px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);"> 输入 </section></li> </ol> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 从文件中读入到字节数组中<br style="outline: 0px;">byte[] copyToByteArray(File <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>)<br style="outline: 0px;">// 从输入流中读入到字节数组中<br style="outline: 0px;">byte[] copyToByteArray(InputStream <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>)<br style="outline: 0px;">// 从输入流中读入到字符串中<br style="outline: 0px;">String copyToString(Reader <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>)<br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">输出</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 从字节数组到文件<br style="outline: 0px;">void copy(byte[] <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>, File out)<br style="outline: 0px;">// 从文件到文件<br style="outline: 0px;">int copy(File <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>, File out)<br style="outline: 0px;">// 从字节数组到输出流<br style="outline: 0px;">void copy(byte[] <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>, OutputStream out) <br style="outline: 0px;">// 从输入流到输出流<br style="outline: 0px;">int copy(InputStream <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>, OutputStream out) <br style="outline: 0px;">// 从输入流到输出流<br style="outline: 0px;">int copy(Reader <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>, Writer out)<br style="outline: 0px;">// 从字符串到输出流<br style="outline: 0px;">void copy(String <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>, Writer out)<br style="outline: 0px;"></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 1.2em;margin-bottom: 1em;outline: 0px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(53, 179, 120);">ResourceUtils</h3> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">从资源路径获取文件</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 判断字符串是否是一个合法的 URL 字符串。<br style="outline: 0px;">static boolean isUrl(String resourceLocation)<br style="outline: 0px;">// 获取 URL<br style="outline: 0px;">static URL getURL(String resourceLocation) <br style="outline: 0px;">// 获取文件(在 JAR 包内无法正常使用,需要是一个独立的文件)<br style="outline: 0px;">static File getFile(String resourceLocation)<br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">Resource</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 文件系统资源 D:\...<br style="outline: 0px;">FileSystemResource<br style="outline: 0px;">// URL 资源,如 file://... http://...<br style="outline: 0px;">UrlResource<br style="outline: 0px;">// 类路径下的资源,classpth:...<br style="outline: 0px;">ClassPathResource<br style="outline: 0px;">// Web 容器上下文中的资源(jar 包、war 包)<br style="outline: 0px;">ServletContextResource<br style="outline: 0px;">// 判断资源是否存在<br style="outline: 0px;">boolean exists()<br style="outline: 0px;">// 从资源中获得 File 对象<br style="outline: 0px;">File getFile()<br style="outline: 0px;">// 从资源中获得 URI 对象<br style="outline: 0px;">URI getURI()<br style="outline: 0px;">// 从资源中获得 URI 对象<br style="outline: 0px;">URL getURL()<br style="outline: 0px;">// 获得资源的 InputStream<br style="outline: 0px;">InputStream getInputStream()<br style="outline: 0px;">// 获得资源的描述信息<br style="outline: 0px;">String getDescription()<br style="outline: 0px;"></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 1.2em;margin-bottom: 1em;outline: 0px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(53, 179, 120);">StreamUtils</h3> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">输入</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">void copy(byte[] <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>, OutputStream out)<br style="outline: 0px;">int copy(InputStream <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>, OutputStream out)<br style="outline: 0px;">void copy(String <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>, Charset charset, OutputStream out)<br style="outline: 0px;">long copyRange(InputStream <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>, OutputStream out, long start, long end)<br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">输出</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">byte[] copyToByteArray(InputStream <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>)<br style="outline: 0px;">String copyToString(InputStream <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>, Charset charset)<br style="outline: 0px;">// 舍弃输入流中的内容<br style="outline: 0px;">int drain(InputStream <span style="outline: 0px;color: rgb(249, 38, 114);font-weight: bold;line-height: 26px;">in</span>) <br style="outline: 0px;"></code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 1em;margin-bottom: 0rem;padding-top: 0.5em;padding-bottom: 0.5em;outline: 0px;font-weight: bold;font-size: 23px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 32px;color: rgb(53, 179, 120);display: inline-block;border-bottom: 0px solid rgb(53, 179, 120);border-top-color: rgb(53, 179, 120);border-right-color: rgb(53, 179, 120);border-left-color: rgb(53, 179, 120);">反射、AOP</h2> <h3 data-tool="mdnice编辑器" style="margin-top: 1.2em;margin-bottom: 1em;outline: 0px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(53, 179, 120);">ReflectionUtils</h3> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">获取方法</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 在类中查找指定方法<br style="outline: 0px;">Method findMethod(Class<?> clazz, String name) <br style="outline: 0px;">// 同上,额外提供方法参数类型作查找条件<br style="outline: 0px;">Method findMethod(Class<?> clazz, String name, Class<?>... paramTypes) <br style="outline: 0px;">// 获得类中所有方法,包括继承而来的<br style="outline: 0px;">Method[] getAllDeclaredMethods(Class<?> leafClass) <br style="outline: 0px;">// 在类中查找指定构造方法<br style="outline: 0px;">Constructor<T> accessibleConstructor(Class<T> clazz, Class<?>... parameterTypes) <br style="outline: 0px;">// 是否是 equals() 方法<br style="outline: 0px;">boolean isEqualsMethod(Method method) <br style="outline: 0px;">// 是否是 hashCode() 方法 <br style="outline: 0px;">boolean isHashCodeMethod(Method method) <br style="outline: 0px;">// 是否是 toString() 方法<br style="outline: 0px;">boolean isToStringMethod(Method method) <br style="outline: 0px;">// 是否是从 Object 类继承而来的方法<br style="outline: 0px;">boolean isObjectMethod(Method method) <br style="outline: 0px;">// 检查一个方法是否声明抛出指定异常<br style="outline: 0px;">boolean declaresException(Method method, Class<?> exceptionType) </code></pre> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">执行方法</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 执行方法<br style="outline: 0px;">Object invokeMethod(Method method, Object target) <br style="outline: 0px;">// 同上,提供方法参数<br style="outline: 0px;">Object invokeMethod(Method method, Object target, Object... args) <br style="outline: 0px;">// 取消 Java 权限检查。以便后续执行该私有方法<br style="outline: 0px;">void makeAccessible(Method method) <br style="outline: 0px;">// 取消 Java 权限检查。以便后续执行私有构造方法<br style="outline: 0px;">void makeAccessible(Constructor<?> ctor) <br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">获取字段</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 在类中查找指定属性<br style="outline: 0px;">Field findField(Class<?> clazz, String name) <br style="outline: 0px;">// 同上,多提供了属性的类型<br style="outline: 0px;">Field findField(Class<?> clazz, String name, Class<?> <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">type</span>) <br style="outline: 0px;">// 是否为一个 <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">"public static final"</span> 属性<br style="outline: 0px;">boolean isPublicStaticFinal(Field field) <br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">设置字段</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 获取 target 对象的 field 属性值<br style="outline: 0px;">Object getField(Field field, Object target) <br style="outline: 0px;">// 设置 target 对象的 field 属性值,值为 value<br style="outline: 0px;">void setField(Field field, Object target, Object value) <br style="outline: 0px;">// 同类对象属性对等赋值<br style="outline: 0px;">void shallowCopyFieldState(Object src, Object dest)<br style="outline: 0px;">// 取消 Java 的权限控制检查。以便后续读写该私有属性<br style="outline: 0px;">void makeAccessible(Field field) <br style="outline: 0px;">// 对类的每个属性执行 callback<br style="outline: 0px;">void doWithFields(Class<?> clazz, ReflectionUtils.FieldCallback <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">fc</span>) <br style="outline: 0px;">// 同上,多了个属性过滤功能。<br style="outline: 0px;">void doWithFields(Class<?> clazz, ReflectionUtils.FieldCallback <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">fc</span>, <br style="outline: 0px;"> ReflectionUtils.FieldFilter ff) <br style="outline: 0px;">// 同上,但不包括继承而来的属性<br style="outline: 0px;">void doWithLocalFields(Class<?> clazz, ReflectionUtils.FieldCallback <span style="outline: 0px;color: rgb(166, 226, 46);line-height: 26px;">fc</span>) <br style="outline: 0px;"></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 1.2em;margin-bottom: 1em;outline: 0px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(53, 179, 120);">AopUtils</h3> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">判断代理类型</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 判断是不是 Spring 代理对象<br style="outline: 0px;">boolean isAopProxy()<br style="outline: 0px;">// 判断是不是 jdk 动态代理对象<br style="outline: 0px;">isJdkDynamicProxy()<br style="outline: 0px;">// 判断是不是 CGLIB 代理对象<br style="outline: 0px;">boolean isCglibProxy()<br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">获取被代理对象的 class</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">// 获取被代理的目标 class<br style="outline: 0px;">Class<?> getTargetClass()<br style="outline: 0px;"></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 1.2em;margin-bottom: 1em;outline: 0px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(53, 179, 120);">AopContext</h3> <p data-tool="mdnice编辑器" style="margin: 1em 4px;padding-top: 8px;padding-bottom: 8px;outline: 0px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;line-height: 26px;color: black;">获取当前对象的代理对象</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 0.75px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/lpHDr05YrISuFMvQw2utdv8E6hq5dia3w8bMKj0OlstfMbCjOuOgiaibaGOq029cKKQInjGicAeoExLAOxgZnibUia0klnNM7Jic0tS/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(39, 40, 34);border-radius: 5px;">Object currentProxy()</code></pre> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding-right: 10px;padding-left: 10px;outline: 0px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;counter-reset: counterh1 0 counterh2 0 counterh3 0;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;visibility: visible;"> <p style="outline: 0px;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: right;line-height: 1.6;word-break: break-word;counter-reset: counterh1 0 counterh2 0 counterh3 0;"><span style="outline: 0px;font-size: 12px;color: rgb(178, 178, 178);"></span></p> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-bottom: 0px;padding-right: 10px;padding-left: 10px;outline: 0px;white-space: normal;color: black;font-size: 16px;text-align: left;letter-spacing: 0px;background-color: rgb(255, 255, 255);line-height: 1.6;word-break: break-word;font-family: PingFangSC-Light;"> <h3 data-tool="mdnice编辑器" style="outline: 0px;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: right;"><em style="outline: 0px;color: rgb(136, 136, 136);font-size: 12px;letter-spacing: 0.5px;"></em></h3> </section> <section> <span style="color: rgba(0, 0, 0, 0.5);font-size: 15px;letter-spacing: 0.034em;"><span style="color: rgb(136, 136, 136);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 12px;letter-spacing: 0.75px;text-align: left;background-color: rgb(251, 249, 253);">作者:CadeCode</span><br style="color: rgb(136, 136, 136);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 12px;letter-spacing: 0.75px;text-align: left;white-space: normal;background-color: rgb(251, 249, 253);outline: 0px;visibility: visible;"><span style="color: rgb(136, 136, 136);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 12px;letter-spacing: 0.75px;text-align: left;background-color: rgb(251, 249, 253);">地址:https://juejin.cn/post/7043403364020781064</span></span> </section>
作者:微信小助手
<p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;"><span style="font-weight: 700;color: rgb(248, 57, 41);">大家好,我是不才陈某~</span></p> <h2 data-tool="mdnice编辑器" style="margin-top: 20px;margin-right: 10px;font-weight: bold;font-size: 22px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="padding-bottom: 10px;font-size: 18px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;">一、什么是SQL注入器</span></h2> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">我们在使用Mybatis-Plus时,dao层都会去继承BaseMapper接口,这样就可以用BaseMapper接口所有的方法,BaseMapper中每一个方法其实就是一个SQL注入器</p> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">在Mybatis-Plus的核心(core)包下,提供的默认可注入方法有这些:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="1.6115288220551378" data-w="399" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;height: auto !important;" src="/upload/c7bdb97d428de1d8766a21376a0adec7.jpg"> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">那如果我们想自定义SQL注入器呢,我们该如何去做?</p> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">比如在Mybatis-Plus中调用updateById方法进行数据更新默认情况下是不能更新空值字段的。</p> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">而在实际开发过程中,往往会遇到需要将字段值更新为空值的情况。</p> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">那如何让Mybatis-Plus支持空值更新呢?</p> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">如果仅是想实现支持更新空值字段并不需要我们自定义SQL注入器,因为Mybatis-Plus提供了几个扩展SQL注入器。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 20px;margin-right: 10px;font-weight: bold;font-size: 22px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="padding-bottom: 10px;font-size: 18px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;">二、内置扩展SQL注入器有哪些?</span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">1、自带扩展SQL注入器</span></h3> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">Mybatis-Plus 扩展SQL注入器在扩展包下,为我们提供了可扩展的可注入方法:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.6810126582278481" data-w="395" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;height: auto !important;" src="/upload/2ab752de7c7b4ed7dc38c705b429ea55.jpg"> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">AlwaysUpdateSomeColumnById</code> : 根据id更新字段(全量更新不忽略null字段),updateById默认会自动忽略实体中null值字段。</p> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">InsertBatchSomeColumn</code> : 真实批量插入,saveBatch其实是伪批量插入。</p> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">LogicDeleteBatchByIds</code> : 逻辑删除增加填充功能,比如删除的时候填充更新时间、更新人。</p> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">Upsert</code> : 插入一条数据(选择字段插入)。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">2、SQL注入器全局配置</span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-size: 16px;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQTjfX5NJyPptED2lCiagzic2Zw2ia5CXRJic7drT9oibFd4EjzV4poj7LiawZiaouCpLxpajj4UrD0NDaa4/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 568px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: black;display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(255, 255, 255);border-radius: 5px;"><span style="color: rgb(100, 56, 32);line-height: 26px;">@Component</span><br><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">class</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">MySqlInjector</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">extends</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">DefaultSqlInjector</span> </span>{<br> <br> <span style="color: rgb(100, 56, 32);line-height: 26px;">@Override</span><br> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> List<AbstractMethod> <span style="color: rgb(28, 0, 207);line-height: 26px;">getMethodList</span><span style="color: rgb(92, 38, 153);line-height: 26px;">(Class<?> mapperClass, TableInfo tableInfo)</span> </span>{<br> List<AbstractMethod> methodList = <span style="color: rgb(170, 13, 145);line-height: 26px;">super</span>.getMethodList(mapperClass, tableInfo);<br> <span style="color: rgb(0, 116, 0);line-height: 26px;">/**<br> * 把两个扩展内置扩展SQL注入器注入<br> */</span><br> methodList.add(<span style="color: rgb(170, 13, 145);line-height: 26px;">new</span> InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));<br> methodList.add(<span style="color: rgb(170, 13, 145);line-height: 26px;">new</span> AlwaysUpdateSomeColumnById(i -> i.getFieldFill() != FieldFill.INSERT));<br> <span style="color: rgb(170, 13, 145);line-height: 26px;">return</span> methodList;<br> }<br>}<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">3、自定义Mapper</span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-size: 16px;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQTjfX5NJyPptED2lCiagzic2Zw2ia5CXRJic7drT9oibFd4EjzV4poj7LiawZiaouCpLxpajj4UrD0NDaa4/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 568px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: black;display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(255, 255, 255);border-radius: 5px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">interface</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">MyBaseMapper</span><<span style="color: rgb(92, 38, 153);line-height: 26px;">T</span>> <span style="color: rgb(170, 13, 145);line-height: 26px;">extends</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">BaseMapper</span><<span style="color: rgb(92, 38, 153);line-height: 26px;">T</span>> </span>{<br> <br> <span style="color: rgb(0, 116, 0);line-height: 26px;">/**<br> * 全字段更新,不会忽略null值<br> *<br> * <span style="font-weight: bold;line-height: 26px;">@param</span> entity 实体对象<br> */</span><br> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">int</span> <span style="color: rgb(28, 0, 207);line-height: 26px;">alwaysUpdateSomeColumnById</span><span style="color: rgb(92, 38, 153);line-height: 26px;">(@Param(<span style="color: rgb(196, 26, 22);line-height: 26px;">"et"</span>)</span> T entity)</span>;<br><br> <span style="color: rgb(0, 116, 0);line-height: 26px;">/**<br> * 全量插入,等价于insert<br> * <br> * <span style="font-weight: bold;line-height: 26px;">@param</span> entityList 实体集合<br> */</span><br> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">int</span> <span style="color: rgb(28, 0, 207);line-height: 26px;">insertBatchSomeColumn</span><span style="color: rgb(92, 38, 153);line-height: 26px;">(List<T> entityList)</span></span>;<br>}<br></code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 20px;margin-right: 10px;font-weight: bold;font-size: 22px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="padding-bottom: 10px;font-size: 18px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;">三、扩展SQL注入器示例测试</span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">1、用户表</span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-size: 16px;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQTjfX5NJyPptED2lCiagzic2Zw2ia5CXRJic7drT9oibFd4EjzV4poj7LiawZiaouCpLxpajj4UrD0NDaa4/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 568px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: black;display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(255, 255, 255);border-radius: 5px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">CREATE</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">TABLE</span> <span style="color: rgb(196, 26, 22);line-height: 26px;">`user`</span> (<br> <span style="color: rgb(196, 26, 22);line-height: 26px;">`id`</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">int</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">unsigned</span> AUTO_INCREMENT <span style="color: rgb(170, 13, 145);line-height: 26px;">COMMENT</span> <span style="color: rgb(196, 26, 22);line-height: 26px;">'主键'</span>,<br> <span style="color: rgb(196, 26, 22);line-height: 26px;">`username`</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">varchar</span>(<span style="color: rgb(28, 0, 207);line-height: 26px;">128</span>) <span style="color: rgb(170, 13, 145);line-height: 26px;">COMMENT</span> <span style="color: rgb(196, 26, 22);line-height: 26px;">'用户名'</span>,<br> <span style="color: rgb(196, 26, 22);line-height: 26px;">`phone`</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">varchar</span>(<span style="color: rgb(28, 0, 207);line-height: 26px;">32</span>) <span style="color: rgb(170, 13, 145);line-height: 26px;">COMMENT</span> <span style="color: rgb(196, 26, 22);line-height: 26px;">'手机号'</span>,<br> <span style="color: rgb(196, 26, 22);line-height: 26px;">`sex`</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">char</span>(<span style="color: rgb(28, 0, 207);line-height: 26px;">1</span>) <span style="color: rgb(170, 13, 145);line-height: 26px;">COMMENT</span> <span style="color: rgb(196, 26, 22);line-height: 26px;">'性别'</span>,<br> <span style="color: rgb(196, 26, 22);line-height: 26px;">`create_time`</span> datetime <span style="color: rgb(170, 13, 145);line-height: 26px;">COMMENT</span> <span style="color: rgb(196, 26, 22);line-height: 26px;">'创建时间'</span>,<br> <span style="color: rgb(196, 26, 22);line-height: 26px;">`update_time`</span> datetime <span style="color: rgb(170, 13, 145);line-height: 26px;">COMMENT</span> <span style="color: rgb(196, 26, 22);line-height: 26px;">'更新时间'</span>,<br> <span style="color: rgb(196, 26, 22);line-height: 26px;">`deleted`</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">tinyint</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">DEFAULT</span> <span style="color: rgb(196, 26, 22);line-height: 26px;">'0'</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">COMMENT</span> <span style="color: rgb(196, 26, 22);line-height: 26px;">'1、删除 0、未删除'</span>,<br> PRIMARY <span style="color: rgb(170, 13, 145);line-height: 26px;">KEY</span> (<span style="color: rgb(196, 26, 22);line-height: 26px;">`id`</span>)<br>) <span style="color: rgb(170, 13, 145);line-height: 26px;">ENGINE</span>=<span style="color: rgb(170, 13, 145);line-height: 26px;">InnoDB</span> AUTO_INCREMENT=<span style="color: rgb(28, 0, 207);line-height: 26px;">1</span> <br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">2、创建对应实体</span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-size: 16px;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQTjfX5NJyPptED2lCiagzic2Zw2ia5CXRJic7drT9oibFd4EjzV4poj7LiawZiaouCpLxpajj4UrD0NDaa4/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 568px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: black;display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(255, 255, 255);border-radius: 5px;"><span style="color: rgb(100, 56, 32);line-height: 26px;">@Data</span><br><span style="color: rgb(100, 56, 32);line-height: 26px;">@Accessors</span>(chain = <span style="color: rgb(170, 13, 145);line-height: 26px;">true</span>)<br><span style="color: rgb(100, 56, 32);line-height: 26px;">@TableName</span>(<span style="color: rgb(196, 26, 22);line-height: 26px;">"user"</span>)<br><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">class</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">UserDO</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">implements</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">Serializable</span> </span>{<br><br> <span style="color: rgb(170, 13, 145);line-height: 26px;">private</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">static</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">final</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">long</span> serialVersionUID = <span style="color: rgb(28, 0, 207);line-height: 26px;">1L</span>;<br><br> <span style="color: rgb(100, 56, 32);line-height: 26px;">@TableId</span>(value = <span style="color: rgb(196, 26, 22);line-height: 26px;">"id"</span>, type = IdType.AUTO)<br> <span style="color: rgb(170, 13, 145);line-height: 26px;">private</span> Integer id;<br> <span style="color: rgb(0, 116, 0);line-height: 26px;">/**<br> * 用户名<br> */</span><br> <span style="color: rgb(100, 56, 32);line-height: 26px;">@TableField</span>(<span style="color: rgb(196, 26, 22);line-height: 26px;">"username"</span>)<br> <span style="color: rgb(170, 13, 145);line-height: 26px;">private</span> String username;<br> <span style="color: rgb(0, 116, 0);line-height: 26px;">/**<br> * 手机号<br> */</span><br> <span style="color: rgb(100, 56, 32);line-height: 26px;">@TableField</span>(<span style="color: rgb(196, 26, 22);line-height: 26px;">"phone"</span>)<br> <span style="color: rgb(170, 13, 145);line-height: 26px;">private</span> String phone;<br> <span style="color: rgb(0, 116, 0);line-height: 26px;">/**<br> * 性别<br> */</span><br> <span style="color: rgb(100, 56, 32);line-height: 26px;">@TableField</span>(<span style="color: rgb(196, 26, 22);line-height: 26px;">"sex"</span>)<br> <span style="color: rgb(170, 13, 145);line-height: 26px;">private</span> String sex;<br> <span style="color: rgb(0, 116, 0);line-height: 26px;">/**<br> * 创建时间<br> */</span><br> <span style="color: rgb(100, 56, 32);line-height: 26px;">@TableField</span>(value = <span style="color: rgb(196, 26, 22);line-height: 26px;">"create_time"</span>,fill = FieldFill.INSERT)<br> <span style="color: rgb(170, 13, 145);line-height: 26px;">private</span> LocalDateTime createTime;<br> <span style="color: rgb(0, 116, 0);line-height: 26px;">/**<br> * 更新时间<br> */</span><br> <span style="color: rgb(100, 56, 32);line-height: 26px;">@TableField</span>(value = <span style="color: rgb(196, 26, 22);line-height: 26px;">"update_time"</span>,fill = FieldFill.INSERT_UPDATE)<br> <span style="color: rgb(170, 13, 145);line-height: 26px;">private</span> LocalDateTime updateTime;<br> <span style="color: rgb(0, 116, 0);line-height: 26px;">/**<br> * 1、删除 0、未删除<br> */</span><br> <span style="color: rgb(100, 56, 32);line-height: 26px;">@TableField</span>(value = <span style="color: rgb(196, 26, 22);line-height: 26px;">"deleted"</span>,fill = FieldFill.INSERT)<br> <span style="color: rgb(170, 13, 145);line-height: 26px;">private</span> Integer deleted;<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">其它有关代码这里就不粘贴了,具体看项目源码。</p> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">我们自定义的Mapper不再继承BaseMapper而是继承MyBaseMapper</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-size: 16px;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQTjfX5NJyPptED2lCiagzic2Zw2ia5CXRJic7drT9oibFd4EjzV4poj7LiawZiaouCpLxpajj4UrD0NDaa4/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 568px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: black;display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(255, 255, 255);border-radius: 5px;"> <span style="color: rgb(0, 116, 0);line-height: 26px;">/**<br> * 通用mapper接口,以后创建其他mapper接口时,不再继承BaseMapper,而是继承MyBaseMapper<br> */</span><br><span style="color: rgb(100, 56, 32);line-height: 26px;">@Mapper</span><br><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">interface</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">UserMapper</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">extends</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">MyBaseMapper</span><<span style="color: rgb(92, 38, 153);line-height: 26px;">UserDO</span>> </span>{<br><br>}<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">3、测试代码</span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-size: 16px;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQTjfX5NJyPptED2lCiagzic2Zw2ia5CXRJic7drT9oibFd4EjzV4poj7LiawZiaouCpLxpajj4UrD0NDaa4/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 568px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: black;display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(255, 255, 255);border-radius: 5px;"><span style="color: rgb(100, 56, 32);line-height: 26px;">@SpringBootTest</span><br><span style="color: rgb(100, 56, 32);line-height: 26px;">@RunWith</span>(SpringRunner<span style="line-height: 26px;">.<span style="color: rgb(170, 13, 145);line-height: 26px;">class</span>)<br>@<span style="color: rgb(92, 38, 153);line-height: 26px;">ComponentScan</span>("<span style="color: rgb(92, 38, 153);line-height: 26px;">com</span>.<span style="color: rgb(92, 38, 153);line-height: 26px;">jincou</span>.<span style="color: rgb(92, 38, 153);line-height: 26px;">mybatisplus</span>.<span style="color: rgb(92, 38, 153);line-height: 26px;">dao</span>")<br><span style="color: rgb(92, 38, 153);line-height: 26px;">public</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">class</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">SqlInjectorTest</span> </span>{<br><br> <span style="color: rgb(100, 56, 32);line-height: 26px;">@Autowired</span><br> <span style="color: rgb(170, 13, 145);line-height: 26px;">private</span> UserMapper mapper;<br> <br> <span style="color: rgb(100, 56, 32);line-height: 26px;">@Test</span><br> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">void</span> <span style="color: rgb(28, 0, 207);line-height: 26px;">alwaysUpdateSomeColumnById</span><span style="color: rgb(92, 38, 153);line-height: 26px;">()</span> </span>{<br> UserDO user = <span style="color: rgb(170, 13, 145);line-height: 26px;">new</span> UserDO();<br> user.setUsername(<span style="color: rgb(196, 26, 22);line-height: 26px;">"小小"</span>);<br> user.setPhone(<span style="color: rgb(170, 13, 145);line-height: 26px;">null</span>);<br> user.setSex(<span style="color: rgb(196, 26, 22);line-height: 26px;">"女"</span>);<br> user.setId(<span style="color: rgb(28, 0, 207);line-height: 26px;">1</span>);<br> mapper.alwaysUpdateSomeColumnById(user);<br> }<br> <br> <span style="color: rgb(100, 56, 32);line-height: 26px;">@Test</span><br> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">void</span> <span style="color: rgb(28, 0, 207);line-height: 26px;">insertBatchSomeColumn</span><span style="color: rgb(92, 38, 153);line-height: 26px;">()</span> </span>{<br> UserDO user = <span style="color: rgb(170, 13, 145);line-height: 26px;">new</span> UserDO();<br> user.setUsername(<span style="color: rgb(196, 26, 22);line-height: 26px;">"zhangsan"</span>);<br> user.setPhone(<span style="color: rgb(196, 26, 22);line-height: 26px;">"13811111111"</span>);<br> user.setSex(<span style="color: rgb(196, 26, 22);line-height: 26px;">"女"</span>);<br><br> UserDO user1 = <span style="color: rgb(170, 13, 145);line-height: 26px;">new</span> UserDO();<br> user1.setUsername(<span style="color: rgb(196, 26, 22);line-height: 26px;">"lisi"</span>);<br> user1.setPhone(<span style="color: rgb(196, 26, 22);line-height: 26px;">"13822222222"</span>);<br> user1.setSex(<span style="color: rgb(196, 26, 22);line-height: 26px;">"男"</span>);<br><br> ArrayList<UserDO> userDOS = Lists.newArrayList(user, user1);<br> mapper.insertBatchSomeColumn(userDOS);<br> }<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">alwaysUpdateSomeColumnById方法运行结果</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.07183098591549296" data-w="710" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;height: auto !important;" src="/upload/ec44c8ea10c792a52fa0ca66e8de772e.jpg"> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">insertBatchSomeColumn方法运行结果</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.08870967741935484" data-w="868" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;height: auto !important;" src="/upload/76a4a7f666910f72bf7af2cb1883024c.jpg"> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">成功!</p> <h2 data-tool="mdnice编辑器" style="margin-top: 20px;margin-right: 10px;font-weight: bold;font-size: 22px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="padding-bottom: 10px;font-size: 18px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;">四、如何自定义SQL注入器?</span></h2> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">在实际开发过程中,当Mybatis-Plus自带的一些SQL注入器不满足我们的条件时,我们就需要自定义SQL注入器,整个流程也非常简单</p> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">这里我们以一个很简单的findAll方法为例进行学习。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">在MyBaseMapper中添加findAll方法</span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-size: 16px;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQTjfX5NJyPptED2lCiagzic2Zw2ia5CXRJic7drT9oibFd4EjzV4poj7LiawZiaouCpLxpajj4UrD0NDaa4/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 568px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: black;display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(255, 255, 255);border-radius: 5px;">public interface MyBaseMapper<T> extends BaseMapper<T> {<br> <br> /**<br> * 查询所有用户<br> */<br> List<T> findAll();<br>}<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">2、编写FindAll SQL注入器</span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-size: 16px;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQTjfX5NJyPptED2lCiagzic2Zw2ia5CXRJic7drT9oibFd4EjzV4poj7LiawZiaouCpLxpajj4UrD0NDaa4/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 568px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: black;display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(255, 255, 255);border-radius: 5px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">class</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">FindAll</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">extends</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">AbstractMethod</span> </span>{<br><br> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> <span style="color: rgb(28, 0, 207);line-height: 26px;">FindAll</span><span style="color: rgb(92, 38, 153);line-height: 26px;">()</span> </span>{<br> <span style="color: rgb(170, 13, 145);line-height: 26px;">super</span>(<span style="color: rgb(196, 26, 22);line-height: 26px;">"findAll"</span>);<br> }<br><br><br> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> <span style="color: rgb(28, 0, 207);line-height: 26px;">FindAll</span><span style="color: rgb(92, 38, 153);line-height: 26px;">(String methodName)</span> </span>{<br> <span style="color: rgb(170, 13, 145);line-height: 26px;">super</span>(methodName);<br> }<br><br> <span style="color: rgb(100, 56, 32);line-height: 26px;">@Override</span><br> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> MappedStatement <span style="color: rgb(28, 0, 207);line-height: 26px;">injectMappedStatement</span><span style="color: rgb(92, 38, 153);line-height: 26px;">(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo)</span> </span>{<br> <span style="color: rgb(0, 116, 0);line-height: 26px;">/* 执行 SQL ,动态 SQL 参考类 SqlMethod */</span><br> String sql = <span style="color: rgb(196, 26, 22);line-height: 26px;">"select * from "</span> + tableInfo.getTableName();<br> SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);<br> <span style="color: rgb(170, 13, 145);line-height: 26px;">return</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">this</span>.addSelectMappedStatementForTable(mapperClass, sqlSource, tableInfo);<br> }<br>}<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">3、注册到Spring容器</span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-size: 16px;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQTjfX5NJyPptED2lCiagzic2Zw2ia5CXRJic7drT9oibFd4EjzV4poj7LiawZiaouCpLxpajj4UrD0NDaa4/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 568px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: black;display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(255, 255, 255);border-radius: 5px;"><span style="color: rgb(100, 56, 32);line-height: 26px;">@Component</span><br><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">class</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">MySqlInjector</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">extends</span> <span style="color: rgb(92, 38, 153);line-height: 26px;">DefaultSqlInjector</span> </span>{<br><br> <span style="color: rgb(100, 56, 32);line-height: 26px;">@Override</span><br> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> List<AbstractMethod> <span style="color: rgb(28, 0, 207);line-height: 26px;">getMethodList</span><span style="color: rgb(92, 38, 153);line-height: 26px;">(Class<?> mapperClass, TableInfo tableInfo)</span> </span>{<br> List<AbstractMethod> methodList = <span style="color: rgb(170, 13, 145);line-height: 26px;">super</span>.getMethodList(mapperClass, tableInfo);<br> <span style="color: rgb(0, 116, 0);line-height: 26px;">/**<br> * 自定义SQL注入器注入<br> */</span><br> methodList.add(<span style="color: rgb(170, 13, 145);line-height: 26px;">new</span> FindAll());<br> <span style="color: rgb(170, 13, 145);line-height: 26px;">return</span> methodList;<br> }<br>}<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">4、测试</span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-size: 16px;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQTjfX5NJyPptED2lCiagzic2Zw2ia5CXRJic7drT9oibFd4EjzV4poj7LiawZiaouCpLxpajj4UrD0NDaa4/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 568px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: black;display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(255, 255, 255);border-radius: 5px;"> <span style="color: rgb(100, 56, 32);line-height: 26px;">@Test</span><br> <span style="line-height: 26px;"><span style="color: rgb(170, 13, 145);line-height: 26px;">public</span> <span style="color: rgb(170, 13, 145);line-height: 26px;">void</span> <span style="color: rgb(28, 0, 207);line-height: 26px;">findAll</span><span style="color: rgb(92, 38, 153);line-height: 26px;">()</span> </span>{<br> List<UserDO> userDOS = mapper.findAll();<br> }<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">运行结果</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.2621664050235479" data-w="637" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;height: auto !important;" src="/upload/bd805888c3d3bacd726fecadb343d5c1.jpg"> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">成功!</p> <h2 data-tool="mdnice编辑器" style="margin-top: 20px;margin-right: 10px;font-weight: bold;font-size: 22px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;color: black;"><span style="padding-bottom: 10px;font-size: 18px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;">最后说一句(别白嫖,求关注)</span></h2> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">陈某每一篇文章都是精心输出,如果这篇文章对你有所帮助,或者有所启发的话,帮忙<span style="font-weight: 700;color: rgb(248, 57, 41);">点赞</span>、<span style="font-weight: 700;color: rgb(248, 57, 41);">在看</span>、<span style="font-weight: 700;color: rgb(248, 57, 41);">转发</span>、<span style="font-weight: 700;color: rgb(248, 57, 41);">收藏</span>,你的支持就是我坚持下去的最大动力!</p> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">另外陈某的<a href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&mid=2247524437&idx=1&sn=32699e9afede86fe52136c38f844c620&chksm=fcf7bf98cb80368e5eff366916e6b251fa7ca7526b44202d59032863d89f353545f0c0ebfff2&token=339165402&lang=zh_CN&scene=21#wechat_redirect" data-linktype="2" style="color: rgb(248, 57, 41);border-bottom: 1px solid rgb(248, 57, 41);">知识星球</a>开通了,加入只需<span style="font-weight: 700;color: rgb(248, 57, 41);">129</span>元,星球回馈的价值巨大,目前更新了<span style="font-weight: 700;color: rgb(248, 57, 41);">Spring全家桶实战系列</span>、<span style="font-weight: 700;color: rgb(248, 57, 41);">亿级数据分库分表实战</span>、<span style="font-weight: 700;color: rgb(248, 57, 41);">DDD微服务实战专栏</span>、<span style="font-weight: 700;color: rgb(248, 57, 41);">我要进大厂、Spring,Mybatis等框架源码、架构实战22讲、精尽RocketMQ</span>等....每增加一个专栏价格将上涨20元</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="1.0398148148148147" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;height: auto !important;" src="/upload/d2a99d6b013cd820afa10b391d4794be.png"> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0.8em;margin-bottom: 0.8em;padding-top: 8px;padding-bottom: 8px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;line-height: 1.75;">关注公众号:【码猿技术专栏】,公众号内有超赞的粉丝福利,回复:加群,可以加入技术讨论群,和大家一起讨论技术,吹牛逼!</p> <section class="mp_profile_iframe_wrp" style="margin-bottom: 0px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;white-space: normal;word-spacing: 0.8px;"> <mp-common-profile class="custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-weuitheme="light" data-id="MzU3MDAzNDg1MA==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/19cc2hfD2rA07Je2pY1o0ic2KcPRn44icO8GVcKRdwiaYvrE6bNeTbWPicyV7c7jWmSyzsiaWASjjckzBcsJMJw06pA/0?wx_fmt=png" data-nickname="码猿技术专栏" data-alias="oneswholife" data-signature="前蚂蚁P8,纯粹的技术人,以专栏的形式分享java全栈技术:SSM、Spring全家桶、微服务、MySQL、分布式、中间件、Linux、偶尔讲点运维Jenkins、Nexus、Docker、ELK.." data-from="2" data-weui-theme="light"></mp-common-profile> </section> <section> <span style="color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;"></span> </section> <p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding-right: 10px;padding-left: 10px;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;line-height: 1.6;letter-spacing: 0.034em;color: rgb(63, 63, 63);font-size: 16px;" data-mpa-powered-by="yiban.io"> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">本文章实现最简单全面的Jenkins+docker+springboot 一键自动部署项目,步骤齐全,少走坑路。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">环境</strong>:centos7+git(gitee)</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">简述实现步骤:在docker安装jenkins,配置jenkins基本信息,利用Dockerfile和shell脚本实现项目自动拉取打包并运行。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;text-align: center;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/CKvMdchsUwknicRHRDwTnZuN46ickONvPDRQ5ZgCBK61Fv2iaVCwgczsYoicdFA6463HDwiaOYGBmicmbHZ97RibWPePQ/640?wx_fmt=png");background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;margin-top: 1em;margin-bottom: 10px;"><span style="display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;margin-top: 38px;font-size: 18px;margin-bottom: 10px;">安装docker</span></h2> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">docker 安装社区版本CE</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 确保 yum 包更新到最新。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">yum update<br></code></pre> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 卸载旧版本(如果安装过旧版本的话) </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">yum remove docker docker-common docker-selinux docker-engine<br></code></pre> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 安装需要的软件包 </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">yum install -y yum-utils device-mapper-persistent-data lvm2<br></code></pre> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 设置yum源 </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo<br></code></pre> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 安装docker </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">yum install docker-ce <span style="color: #5c6370;font-style: italic;line-height: 26px;">#由于repo中默认只开启stable仓库,故这里安装的是最新稳定版17.12.0</span><br>yum install <自己的版本> <span style="color: #5c6370;font-style: italic;line-height: 26px;"># 例如:sudo yum install docker-ce-17.12.0.ce</span><br></code></pre> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 启动和开机启动 </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">systemctl start docker<br>systemctl <span style="color: #e6c07b;line-height: 26px;">enable</span> docker<br></code></pre> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 验证安装是否成功 </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">docker version<br></code></pre> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;text-align: center;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/CKvMdchsUwknicRHRDwTnZuN46ickONvPDRQ5ZgCBK61Fv2iaVCwgczsYoicdFA6463HDwiaOYGBmicmbHZ97RibWPePQ/640?wx_fmt=png");background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;margin-top: 1em;margin-bottom: 10px;"><span style="display: none;"></span><span style="display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;margin-top: 38px;font-size: 18px;margin-bottom: 10px;">安装Jenkins</span></h2> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">Jenkins中文官网:https://www.jenkins.io/zh/</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 安装J enkins </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">docker 安装一切都是那么简单,注意检查8080是否已经占用!如果占用修改端口</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">docker run --name jenkins -u root --rm -d -p 8080:8080 -p 50000:50000 -v /var/jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock jenkinsci/blueocean<br></code></pre> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">如果没改端口号的话</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">安装完成后访问地址-> <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">http://{部署Jenkins所在服务IP}:8080</code></p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">此处会有几分钟的等待时间。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 初始化 Jenkins </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">详情见官网教程-><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">https://www.jenkins.io</code></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 解锁 Jenkins </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">进入Jenkins容器:<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">docker exec -it {Jenkins容器名} bash</code></p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">例如 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">docker exec -it jenkins bash</code></p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">查看密码:<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">cat /var/lib/jenkins/secrets/initialAdminPassword</code></p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">复制密码到输入框里面</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.4394394394394394" src="/upload/8d59f3f7eb01415dce139ba1bf0dca2c.png" data-w="999" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 安装插件 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">选择第一个:安装推荐的插件</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.5387596899224806" src="/upload/f3b276c76c7a256ad95bf13469664741.png" data-w="774" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 创建管理员用户 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">此账户一定要记住哦</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;text-align: center;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/CKvMdchsUwknicRHRDwTnZuN46ickONvPDRQ5ZgCBK61Fv2iaVCwgczsYoicdFA6463HDwiaOYGBmicmbHZ97RibWPePQ/640?wx_fmt=png");background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;margin-top: 1em;margin-bottom: 10px;"><span style="display: none;"></span><span style="display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;margin-top: 38px;font-size: 18px;margin-bottom: 10px;">系统配置</span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 安装需要插件 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">进入【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">首页</code>】–【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">系统管理</code>】–【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">插件管理</code>】–【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">可选插件</code>】</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">搜索以下需要安装的插件,点击安装即可。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.8373493975903614" src="/upload/9eddd8d1f4496301e0b5d34434fac9df.png" data-w="498" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">安装Maven Integration</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">安装Publish Over SSH(如果不需要远程推送,不用安装)</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">如果使用Gitee 码云,安装插件Gitee(Git自带不用安装)</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">配置Maven</p> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">进入【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">首页</code>】–【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">系统管理</code>】–【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">全局配置</code>】,拉到最下面maven–maven安装</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.42962962962962964" src="/upload/6659584065432d290b0c3220f03e4a82.png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"> </figure> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;text-align: center;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/CKvMdchsUwknicRHRDwTnZuN46ickONvPDRQ5ZgCBK61Fv2iaVCwgczsYoicdFA6463HDwiaOYGBmicmbHZ97RibWPePQ/640?wx_fmt=png");background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;margin-top: 1em;margin-bottom: 10px;"><span style="display: none;"></span><span style="display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;margin-top: 38px;font-size: 18px;margin-bottom: 10px;">创建任务</span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 新建任务 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">点击【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">新建任务</code>】,输入任务名称,点击构建一个自由风格的软件项目</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.28762135922330095" src="/upload/97c7957c127aa781865f3635ef57c01b.png" data-w="824" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 源码管理 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">点击【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">源码管理</code>】–【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">Git</code>】,输入仓库地址,添加凭证,选择好凭证即可。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><img class="rich_pages wxw-img" data-ratio="0.7423664122137404" src="/upload/45ec719f982c0fbfdc2db5ae180713b7.png" data-w="524" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"><img class="rich_pages wxw-img" data-ratio="1.1605504587155964" src="/upload/df8d51c7da22c52124749e35b4af317f.png" data-w="436" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 构建触发器 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">点击【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">构建触发器</code>】–【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">构建</code>】–【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">增加构建步骤</code>】–【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">调用顶层Maven目标</code>】–【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">填写配置</code>】–【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">保存</code>】</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.969047619047619" src="/upload/6b14f58fb5a197dad6f2da79e6963e76.png" data-w="840" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"> </figure> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">此处命令只是install,看是否能生成jar包</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">clean install -Dmaven.test.skip=<span style="color: #56b6c2;line-height: 26px;">true</span><br></code></pre> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.3881401617250674" src="/upload/281eac54a2bd6a87fe95917d053e78fe.png" data-w="742" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 保存 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">点击【<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">保存</code>】按钮即可</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;text-align: center;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/CKvMdchsUwknicRHRDwTnZuN46ickONvPDRQ5ZgCBK61Fv2iaVCwgczsYoicdFA6463HDwiaOYGBmicmbHZ97RibWPePQ/640?wx_fmt=png");background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;margin-top: 1em;margin-bottom: 10px;"><span style="display: none;"></span><span style="display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;margin-top: 38px;font-size: 18px;margin-bottom: 10px;">测试</span></h2> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">该功能测试是否能正常打包</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 构建 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">点击构建按钮<img class="rich_pages wxw-img" data-ratio="0.10740740740740741" src="/upload/40436b09757fc0f0a89ea481dc679255.png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 查看日志 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">点击正在构建的任务,或者点击任务名称,进入详情页面,查看控制台输出,看是否能成功打成jar包。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">该处日志第一次可能下载依赖jar包失败,再次点击构建即可成功。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><img class="rich_pages wxw-img" data-ratio="1.083086053412463" src="/upload/14a11725cee4922edebd36da6f6bed52.png" data-w="674" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"><img class="rich_pages wxw-img" data-ratio="0.5918803418803419" src="/upload/fddabd4b6ddcb1aab302f040f3ffefc0.png" data-w="936" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 查看项目位置 </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #e6c07b;line-height: 26px;">cd</span> /var/jenkins_home/workspace<br></code></pre> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">ll</code>命令即可查看是否存在</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;text-align: center;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/CKvMdchsUwknicRHRDwTnZuN46ickONvPDRQ5ZgCBK61Fv2iaVCwgczsYoicdFA6463HDwiaOYGBmicmbHZ97RibWPePQ/640?wx_fmt=png");background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;margin-top: 1em;margin-bottom: 10px;"><span style="display: none;"></span><span style="display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;margin-top: 38px;font-size: 18px;margin-bottom: 10px;">运行项目</span></h2> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">因为我们项目和jenkins在同一台服务器,所以我们用shell脚本运行项目,原理既是通过dockerfile 打包镜像,然后docker运行即可。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> Dockerfile </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">在springboot项目根目录新建一个名为Dockerfile的文件,注意没有后缀名,其内容如下:(大致就是使用jdk8,把jar包添加到docker然后运行prd配置文件)</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">FROM jdk:8<br>VOLUME /tmp<br>ADD target/zx-order-0.0.1-SNAPSHOT.jar app.jar<br>EXPOSE 8888<br>ENTRYPOINT [<span style="color: #98c379;line-height: 26px;">"Bash"</span>,<span style="color: #98c379;line-height: 26px;">"-DBash.security.egd=file:/dev/./urandom"</span>,<span style="color: #98c379;line-height: 26px;">"-jar"</span>,<span style="color: #98c379;line-height: 26px;">"/app.jar"</span>,<span style="color: #98c379;line-height: 26px;">"--spring.profiles.active=prd"</span>]<br></code></pre> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 修改jenkins任务配置 </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="1.0557029177718833" src="/upload/b26e59f2d907281544b6ab205990b05.png" data-w="754" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"> </figure> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">配置如下:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.575" src="/upload/8cfa25731d5c07712801ba37c954baa7.png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"> </figure> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">-t:指定新镜像名<br>.:表示Dockfile在当前路径<br><span style="color: #e6c07b;line-height: 26px;">cd</span> /var/jenkins_home/workspace/zx-order-api<br>docker stop zx-order || <span style="color: #56b6c2;line-height: 26px;">true</span><br>docker rm zx-order || <span style="color: #56b6c2;line-height: 26px;">true</span><br>docker rmi zx-order || <span style="color: #56b6c2;line-height: 26px;">true</span><br>docker build -t zx-order .<br>docker run -d -p 8888:8888 --name zx-order zx-order:latest<br></code></pre> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">备注:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">我上图用了docker logs -f 是为了方便看日志,真实不要用,因为会一直等待日志,构建任务会失败</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">加|| true 是如果命令执行失败也会继续实行,为了防止第一次没有该镜像报错</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">保存</p> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">点击保存即可</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 构建 </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.6337148803329865" src="/upload/95eae505deb12253b0baa05e2bca5523.png" data-w="961" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;"> </figure> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">查看jenkins控制台输出,输出如下,证明成功!</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 验证 </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">docker ps 查看是否有自己的容器<br>docker logs 自己的容器名 查看日志是否正确<br></code></pre> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">浏览器访问项目试一试</p> </section>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;padding: 5px;font-size: 16px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;" data-mpa-powered-by="yiban.io"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">开发过<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">SaaS</code>系统平台的小伙伴一定对<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">多租户</code>这个概念不陌生,简单来说一个租户就是一个公司客户,多个租户共用同一个SaaS系统,一旦SaaS系统不可用,那么所有的租户都不可用。你可以这么理解SaaS系统就像一栋大楼,而租户就是大楼里面租办公楼层的公司,平时每家公司做着自己的业务,互不干扰,但是一旦大楼的电梯坏了,那么影响到的就是所有的公司。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">多租户问题,其是一种架构设计方式,就是在一台或者一组服务器上运行的SaaS系统,可以为多个租户(客户)提供服务,目的是为了让多个租户在互联网环境下使用同一套程序,且保证租户间的数据隔离。从这种架构设计的模式上,不难看出来,多租户架构的重点就是同一套程序下多个租户数据的隔离。由于租户数据是集中存储的,所以要实现数据的安全性,就是看能否实现对租户数据的隔离,防止租户数据不经意或被他人恶意地获取和篡改。在讲多租户数据隔离实现之前,先来看看什么是<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">SaaS系统</code>。</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;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;"><span style="color: rgb(248, 57, 41);">什么是SaaS系统</span>?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">SaaS平台是运营saas软件的平台。SaaS提供商为企业搭建信息化所需要的所有网络基础设施及软件、硬件运作平台,并负责所有前期的实施、后期的维护等一系列服务,租户(企业)无需购买软硬件、建设机房、招聘IT人员,即可通过互联网使用信息系统。SaaS 是一种软件布局模型,其应用专为网络交付而设计,便于用户通过互联网托管、部署及接入。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">简单来说就是租户给SaaS平台付租金就能使用平台提供的功能服务,当下比较典型就是各种云平台、云服务厂商。</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;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;">多租户数据隔离架构设计</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">目前saas多租户系统的数据隔离有三种架构设计,即为每个租户提供独立的数据库、独立的表空间、按字段区分租户,每种方案都有其各自的适用情况。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">一个租户独立一个数据库</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">一个租户独立使用一个数据库,那就意味着我们的SaaS系统需要连接多个数据库,这种实现方案其实就和分库分表架构设计是一样的,好处就是数据隔离级别高、安全性好,毕竟一个租户单用一个数据库,但是物理硬件成本,维护成本也变高了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">独立的表空间</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这种方案的实现方式,就是所有租户共用一个数据库系统,但是每个租户在数据库系统中拥有一个独立的表空间。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">按租户id字段隔离租户</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这种方案是多租户方案中最简单的数据隔离方法,即在每张表中都添加一个用于区分租户的字段(如tenant_id或org_id啥的)来标识每条数据属于哪个租户,当进行查询的时候每条语句都要添加该字段作为过滤条件,其特点是所有租户的数据全都存放在同一个表中,数据的隔离性是最低的,完全是通过字段来区分的,很容易把数据搞串或者误操作。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">三种数据隔离架构设计的对比如下:</p> <section data-tool="mdnice编辑器" style="overflow-x: auto;"> <table> <thead> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <th style="border-top-width: 1px;border-color: rgb(204, 204, 204);background-color: rgb(219, 217, 216);min-width: 85px;text-align: left;">隔离方案</th> <th style="border-top-width: 1px;border-color: rgb(204, 204, 204);background-color: rgb(219, 217, 216);min-width: 85px;text-align: left;">成本</th> <th style="border-top-width: 1px;border-color: rgb(204, 204, 204);background-color: rgb(219, 217, 216);min-width: 85px;text-align: left;">支持租户数量</th> <th style="border-top-width: 1px;border-color: rgb(204, 204, 204);background-color: rgb(219, 217, 216);min-width: 85px;text-align: left;">优点</th> <th style="border-top-width: 1px;border-color: rgb(204, 204, 204);background-color: rgb(219, 217, 216);min-width: 85px;text-align: left;">缺点</th> </tr> </thead> <tbody style="border-width: 0px;border-style: initial;border-color: initial;"> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">独立数据库系统</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">高</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">少</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">数据隔离级别高,安全性,可以针对单个租户开发个性化需求</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">数据库独立安装,物理成本和维护成本都比较高</td> </tr> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: rgb(248, 248, 248);"> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">独立的表空间</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">中</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">较多</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">提供了一定程度的逻辑数据隔离,一个数据库系统可支持多个租户</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">数据库管理比较困难,表繁多,同时数据修复稍复杂</td> </tr> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">按租户id字段区分</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">低</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">多</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">维护和购置成本最低,每个数据库能够支持的租户数量最多</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;">隔离级别最低,安全性也最低</td> </tr> </tbody> </table> </section> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">大部分公司都是采用第三种:<span style="font-weight: 700;color: rgb(248, 57, 41);">按租户id字段隔离租户</span>架构设计实现多租户数据隔离的。接下来我们就来看看代码层面怎么实现多租户数据隔离的。关注公众号:码猿技术专栏,回复关键词:1111 获取阿里内部Java性能调优手册!</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;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;">mybatis-plus优雅实现多租户数据权限隔离</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">上面我们说过<span style="font-weight: 700;color: rgb(248, 57, 41);">按租户id字段隔离租户</span>这种方式就是在获取数据的时候对每一条SQL语句添加租户id作为过滤条件来隔离租户数据的。但是这样意味着每个查询SQL都必须加上租户id这个过滤条件,如果漏加就意味着会查询出不同租户的数据,这是绝对不允许的,同时每个查询接口都需要手动设置过滤条件,重复劳动,一点都不够优雅。这时候就不得不说说mybatis-plus的多租户插件了,看看它如何优雅实现多租户隔离的?再讲述之前,我们先思考一下如何优雅实现数据隔离?首先我们要求每一条SQL都加上租户id这个过滤条件,这意味着我们需要解析原始SQL在合适的地方加上租户id过滤条件,我们知道mybatis提供扩展点就是拦截器,可以对SQL语句处理前后进行增强逻辑,分页插件就是这么做的,所以我们这里要增强SQL自然也是这样,接下来我们就来看看mybatis-plus多租户插件是怎么实现多租户数据隔离的,插件官网介绍地址:https://www.baomidou.com/pages/aef2f2/#tenantlineinnerinterceptor,该拦截器部分源码如下:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQccdCenu6ia845wTA3XgZ9RhjniclKHdohqH5srY3xFPQfUIAQzEySOrHUmCNDpCIxK5XrtichXV9Dib/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #aa0d91;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">class</span> <span style="color: #5c2699;line-height: 26px;">TenantLineInnerInterceptor</span> <span style="color: #aa0d91;line-height: 26px;">extends</span> <span style="color: #5c2699;line-height: 26px;">JsqlParserSupport</span> <span style="color: #aa0d91;line-height: 26px;">implements</span> <span style="color: #5c2699;line-height: 26px;">InnerInterceptor</span> </span>{<br> <span style="color: #007400;line-height: 26px;">// 多租户处理器</span><br> <span style="color: #aa0d91;line-height: 26px;">private</span> TenantLineHandler tenantLineHandler;<br><br> <span style="color: #007400;line-height: 26px;">// 改SQL,添加多租户id条件</span><br> <span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span> <span style="color: #aa0d91;line-height: 26px;">void</span> <span style="color: #1c00cf;line-height: 26px;">beforeQuery</span><span style="color: #5c2699;line-height: 26px;">(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)</span> <span style="color: #aa0d91;line-height: 26px;">throws</span> SQLException </span>{<br> <span style="color: #aa0d91;line-height: 26px;">if</span> (!InterceptorIgnoreHelper.willIgnoreTenantLine(ms.getId())) {<br> MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);<br> mpBs.sql(<span style="color: #aa0d91;line-height: 26px;">this</span>.parserSingle(mpBs.sql(), (Object)<span style="color: #aa0d91;line-height: 26px;">null</span>));<br> }<br> }<br><br> <span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span> <span style="color: #aa0d91;line-height: 26px;">void</span> <span style="color: #1c00cf;line-height: 26px;">beforePrepare</span><span style="color: #5c2699;line-height: 26px;">(StatementHandler sh, Connection connection, Integer transactionTimeout)</span> </span>{<br> MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);<br> MappedStatement ms = mpSh.mappedStatement();<br> SqlCommandType sct = ms.getSqlCommandType();<br> <span style="color: #aa0d91;line-height: 26px;">if</span> (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {<br> <span style="color: #aa0d91;line-height: 26px;">if</span> (InterceptorIgnoreHelper.willIgnoreTenantLine(ms.getId())) {<br> <span style="color: #aa0d91;line-height: 26px;">return</span>;<br> }<br><br> MPBoundSql mpBs = mpSh.mPBoundSql();<br> mpBs.sql(<span style="color: #aa0d91;line-height: 26px;">this</span>.parserMulti(mpBs.sql(), (Object)<span style="color: #aa0d91;line-height: 26px;">null</span>));<br> }<br><br> }<br> <br> <span style="color: #007400;line-height: 26px;">// 碍于篇幅问题,下面省略的代码就是继承抽象类JsqlParserSupport解析SQL然后添加多租户id条件的,可以自行查看源码</span><br> ......<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">接着我们来看看处理器<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">TenantLineHandler</code>,这是一个接口,需要我们提供自定义实现,指定多租户相关配置:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQccdCenu6ia845wTA3XgZ9RhjniclKHdohqH5srY3xFPQfUIAQzEySOrHUmCNDpCIxK5XrtichXV9Dib/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #aa0d91;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">class</span> <span style="color: #5c2699;line-height: 26px;">TenantDatabaseHandler</span> <span style="color: #aa0d91;line-height: 26px;">implements</span> <span style="color: #5c2699;line-height: 26px;">TenantLineHandler</span> </span>{<br> <span style="color: #aa0d91;line-height: 26px;">private</span> <span style="color: #aa0d91;line-height: 26px;">final</span> Set<String> ignoreTables = <span style="color: #aa0d91;line-height: 26px;">new</span> HashSet<>();<br><br> <span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span> <span style="color: #1c00cf;line-height: 26px;">TenantDatabaseHandler</span><span style="color: #5c2699;line-height: 26px;">(TenantProperties properties)</span> </span>{<br> <span style="color: #007400;line-height: 26px;">// 将配置文件配置的忽略表名同步大小写,适配不同写法</span><br> properties.getIgnoreTables().forEach(table -> {<br> ignoreTables.add(table.toLowerCase());<br> ignoreTables.add(table.toUpperCase());<br> });<br> }<br><br> <span style="color: #007400;line-height: 26px;">/**<br> * 获取租户字段名<br> * <p><br> * 默认字段名叫: tenant_id,我这里使用org_id<br> *<br> * <span style="font-weight: bold;line-height: 26px;">@return</span> 租户字段名<br> */</span><br> <span style="color: #643820;line-height: 26px;">@Override</span><br> <span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span> String <span style="color: #1c00cf;line-height: 26px;">getTenantIdColumn</span><span style="color: #5c2699;line-height: 26px;">()</span> </span>{<br> <span style="color: #aa0d91;line-height: 26px;">return</span> <span style="color: #c41a16;line-height: 26px;">"org_id"</span>;<br> }<br><br><br> <span style="color: #643820;line-height: 26px;">@Override</span><br> <span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span> Expression <span style="color: #1c00cf;line-height: 26px;">getTenantId</span><span style="color: #5c2699;line-height: 26px;">()</span> </span>{<br> <span style="color: #007400;line-height: 26px;">// 这里通过登录信息上下文返回租户id给多租户拦截器增强SQL使用</span><br> <span style="color: #aa0d91;line-height: 26px;">return</span> <span style="color: #aa0d91;line-height: 26px;">new</span> LongValue(RequestUserHolder.getCurrentUser().getOrgId());<br> }<br><br> <span style="color: #643820;line-height: 26px;">@Override</span><br> <span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span> <span style="color: #aa0d91;line-height: 26px;">boolean</span> <span style="color: #1c00cf;line-height: 26px;">ignoreTable</span><span style="color: #5c2699;line-height: 26px;">(String tableName)</span> </span>{<br> <span style="color: #007400;line-height: 26px;">// 忽略多租户的表</span><br> <span style="color: #aa0d91;line-height: 26px;">return</span> CollUtil.contains(ignoreTables, tableName);<br> }<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">配置属性如下:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQccdCenu6ia845wTA3XgZ9RhjniclKHdohqH5srY3xFPQfUIAQzEySOrHUmCNDpCIxK5XrtichXV9Dib/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #643820;line-height: 26px;">@ConfigurationProperties</span>(prefix = <span style="color: #c41a16;line-height: 26px;">"ptc.tenant"</span>)<br><span style="color: #643820;line-height: 26px;">@Data</span><br><span style="color: #aa0d91;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">class</span> <span style="color: #5c2699;line-height: 26px;">TenantProperties</span> </span>{<br><br><br> <span style="color: #007400;line-height: 26px;">/**<br> * 全局控制是否开启多租户功能<br> */</span><br> <span style="color: #aa0d91;line-height: 26px;">private</span> Boolean enable = Boolean.TRUE;<br><br> <span style="color: #007400;line-height: 26px;">/**<br> * 需要忽略多租户的表<br> *<br> * 即默认所有表都开启多租户的功能,所以记得添加对应的 tenant_id 字段哟<br> */</span><br> <span style="color: #aa0d91;line-height: 26px;">private</span> Set<String> ignoreTables = Collections.emptySet();<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">接下来注入拦截器插件即可:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQccdCenu6ia845wTA3XgZ9RhjniclKHdohqH5srY3xFPQfUIAQzEySOrHUmCNDpCIxK5XrtichXV9Dib/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #643820;line-height: 26px;">@Bean</span><br><span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span> MybatisPlusInterceptor <span style="color: #1c00cf;line-height: 26px;">mybatisPlusInterceptor</span><span style="color: #5c2699;line-height: 26px;">(TenantProperties properties)</span> </span>{<br> MybatisPlusInterceptor mybatisPlusInterceptor = <span style="color: #aa0d91;line-height: 26px;">new</span> MybatisPlusInterceptor();<br> <span style="color: #007400;line-height: 26px;">// 必须保证多租户插件在分页插件之前,这个是 MyBatis-plus 的规定</span><br> <span style="color: #aa0d91;line-height: 26px;">if</span> (properties.getEnable()) {<br> mybatisPlusInterceptor.addInnerInterceptor(<span style="color: #aa0d91;line-height: 26px;">new</span> TenantLineInnerInterceptor(<span style="color: #aa0d91;line-height: 26px;">new</span> TenantDatabaseHandler(properties)));<br> }<br> <span style="color: #007400;line-height: 26px;">// 分页插件</span><br> mybatisPlusInterceptor.addInnerInterceptor(<span style="color: #aa0d91;line-height: 26px;">new</span> PaginationInnerInterceptor());<br> <span style="color: #aa0d91;line-height: 26px;">return</span> mybatisPlusInterceptor;<br> }<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">使用示例如下:这里提供了一个常见的案例:用户和角色关联查询的SQL:<span style="font-weight: 700;color: rgb(248, 57, 41);">getUserList()</span></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQccdCenu6ia845wTA3XgZ9RhjniclKHdohqH5srY3xFPQfUIAQzEySOrHUmCNDpCIxK5XrtichXV9Dib/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"> <span style="color: #aa0d91;line-height: 26px;"><<span style="line-height: 26px;">select</span> <span style="color: #836C28;line-height: 26px;">id</span>=<span style="color: #c41a16;line-height: 26px;">"getUserList"</span> <span style="color: #836C28;line-height: 26px;">resultType</span>=<span style="color: #c41a16;line-height: 26px;">"com.plasticene.textile.entity.User"</span>></span><br> select u.* from user u<br> left join user_role r on u.id = r.user_id<br> <span style="color: #aa0d91;line-height: 26px;"><<span style="line-height: 26px;">where</span>></span><br> <span style="color: #aa0d91;line-height: 26px;"><<span style="line-height: 26px;">if</span> <span style="color: #836C28;line-height: 26px;">test</span>=<span style="color: #c41a16;line-height: 26px;">"query.status != null"</span>></span><br> and u.status = #{query.status}<br> <span style="color: #aa0d91;line-height: 26px;"></<span style="line-height: 26px;">if</span>></span><br> <span style="color: #aa0d91;line-height: 26px;"><<span style="line-height: 26px;">if</span> <span style="color: #836C28;line-height: 26px;">test</span>=<span style="color: #c41a16;line-height: 26px;">"query.roleId != null"</span>></span><br> and r.role_id = #{query.roleId}<br> <span style="color: #aa0d91;line-height: 26px;"></<span style="line-height: 26px;">if</span>></span><br> <span style="color: #aa0d91;line-height: 26px;"><<span style="line-height: 26px;">if</span> <span style="color: #836C28;line-height: 26px;">test</span>=<span style="color: #c41a16;line-height: 26px;">"query.keyword != null"</span>></span><br> and ((u.name like concat('%',#{query.keyword},'%')) or (u.mobile like concat(#{query.keyword},'%')))<br> <span style="color: #aa0d91;line-height: 26px;"></<span style="line-height: 26px;">if</span>></span><br> <span style="color: #aa0d91;line-height: 26px;"><<span style="line-height: 26px;">if</span> <span style="color: #836C28;line-height: 26px;">test</span>=<span style="color: #c41a16;line-height: 26px;">"query.startEntryTime != null"</span>></span><br> and u.entry_time >= #{query.startEntryTime}<br> <span style="color: #aa0d91;line-height: 26px;"></<span style="line-height: 26px;">if</span>></span><br> <span style="color: #aa0d91;line-height: 26px;"><<span style="line-height: 26px;">if</span> <span style="color: #836C28;line-height: 26px;">test</span>=<span style="color: #c41a16;line-height: 26px;">"query.endEntryTime != null"</span>></span><br> <![CDATA[ and u.entry_time <= #{query.endEntryTime}]]><br> <span style="color: #aa0d91;line-height: 26px;"></<span style="line-height: 26px;">if</span>></span><br><br> <span style="color: #aa0d91;line-height: 26px;"></<span style="line-height: 26px;">where</span>></span><br> group by u.id<br> order by u.id desc<br> <span style="color: #aa0d91;line-height: 26px;"></<span style="line-height: 26px;">select</span>></span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">启动项目,先登录之后使用token掉接口执行下面代码逻辑:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQccdCenu6ia845wTA3XgZ9RhjniclKHdohqH5srY3xFPQfUIAQzEySOrHUmCNDpCIxK5XrtichXV9Dib/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"> <span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span> PageResult<UserDTO> <span style="color: #1c00cf;line-height: 26px;">getList</span><span style="color: #5c2699;line-height: 26px;">(UserQuery query)</span> </span>{<br> Page<UserDTO> page = <span style="color: #aa0d91;line-height: 26px;">new</span> Page<>(query.getPageNo(), query.getPageSize());<br> List<User> userList = userDAO.getUserList(page, query);<br> List<UserDTO> userDTOS = toUserDTOList(userList);<br> <span style="color: #aa0d91;line-height: 26px;">return</span> <span style="color: #aa0d91;line-height: 26px;">new</span> PageResult<>(userDTOS, page.getTotal(), page.getPages());<br> }<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">查看控制台发现:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQccdCenu6ia845wTA3XgZ9RhjniclKHdohqH5srY3xFPQfUIAQzEySOrHUmCNDpCIxK5XrtichXV9Dib/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;">[<span style="color: #1c00cf;line-height: 26px;">1658720355293990912</span>] [DEBUG] [<span style="color: #1c00cf;line-height: 26px;">2023</span>-<span style="color: #1c00cf;line-height: 26px;">05</span>-<span style="color: #1c00cf;line-height: 26px;">17</span> <span style="color: #1c00cf;line-height: 26px;">14</span>:<span style="color: #1c00cf;line-height: 26px;">25</span>:<span style="color: #1c00cf;line-height: 26px;">25.504</span>] [http-nio-<span style="color: #1c00cf;line-height: 26px;">16688</span>-exec-<span style="color: #1c00cf;line-height: 26px;">1</span>@<span style="color: #1c00cf;line-height: 26px;">23652</span>] com.plasticene.textile.dao.UserDAO.getUserList debug : ==> Preparing: SELECT u.* FROM user u LEFT JOIN user_role r ON u.id = r.user_id AND r.org_id = <span style="color: #1c00cf;line-height: 26px;">3</span> WHERE u.org_id = <span style="color: #1c00cf;line-height: 26px;">3</span> GROUP BY u.id ORDER BY u.id DESC LIMIT ?<br>[<span style="color: #1c00cf;line-height: 26px;">1658720355293990912</span>] [DEBUG] [<span style="color: #1c00cf;line-height: 26px;">2023</span>-<span style="color: #1c00cf;line-height: 26px;">05</span>-<span style="color: #1c00cf;line-height: 26px;">17</span> <span style="color: #1c00cf;line-height: 26px;">14</span>:<span style="color: #1c00cf;line-height: 26px;">25</span>:<span style="color: #1c00cf;line-height: 26px;">25.505</span>] [http-nio-<span style="color: #1c00cf;line-height: 26px;">16688</span>-exec-<span style="color: #1c00cf;line-height: 26px;">1</span>@<span style="color: #1c00cf;line-height: 26px;">23652</span>] com.plasticene.textile.dao.UserDAO.getUserList debug : ==> Parameters: <span style="color: #1c00cf;line-height: 26px;">20</span>(Long)<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">user</code>表u加上<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">u.org_id=3</code>这个多租户过滤条件,<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">user_role</code>也同样加上了,说明多租户插件起作用了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">当然如果想忽略掉表<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">user</code>,我们只需要在配置文件如下配置即可:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQccdCenu6ia845wTA3XgZ9RhjniclKHdohqH5srY3xFPQfUIAQzEySOrHUmCNDpCIxK5XrtichXV9Dib/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #836C28;line-height: 26px;">ptc:</span><br> <span style="color: #836C28;line-height: 26px;">tenant:</span><br> <span style="color: #836C28;line-height: 26px;">ignore-tables:</span> <span style="color: #c41a16;line-height: 26px;">user</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这样<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">user</code>表u就不会再加上<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">u.org_id=3</code>这个多租户过滤条件,但是这里有一个细节需要注意,由于<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">user</code>在MySQL中是关键字,所以我有时候为了规范书写SQL,会按照如下编写:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQccdCenu6ia845wTA3XgZ9RhjniclKHdohqH5srY3xFPQfUIAQzEySOrHUmCNDpCIxK5XrtichXV9Dib/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #aa0d91;line-height: 26px;">select</span> u.* <span style="color: #aa0d91;line-height: 26px;">from</span> <span style="color: #c41a16;line-height: 26px;">`user`</span> u<br> <span style="color: #aa0d91;line-height: 26px;">left</span> <span style="color: #aa0d91;line-height: 26px;">join</span> user_role r <span style="color: #aa0d91;line-height: 26px;">on</span> u.id = r.user_id<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这时候你会发现上面配置的忽略表<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">user</code>不起作用,还是会加上<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">u.org_id=3</code>这个多租户过滤条件,跟源码才发现我们上面自定义的多租户处理器<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">TenantLineHandler</code>只对表名进行了大小写适配,然而这里SQL解析出来的表名是: **<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">user</code>**,所以匹配不到配置不起作用。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">当然我们有可能需要针对单一SQL语句不加多租户过滤条件,可以使用<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@InterceptorIgnore</code>注解:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQccdCenu6ia845wTA3XgZ9RhjniclKHdohqH5srY3xFPQfUIAQzEySOrHUmCNDpCIxK5XrtichXV9Dib/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #aa0d91;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">interface</span> <span style="color: #5c2699;line-height: 26px;">UserDAO</span> <span style="color: #aa0d91;line-height: 26px;">extends</span> <span style="color: #5c2699;line-height: 26px;">BaseMapperX</span><<span style="color: #5c2699;line-height: 26px;">User</span>> </span>{<br><br> <span style="color: #643820;line-height: 26px;">@InterceptorIgnore</span>(tenantLine = <span style="color: #c41a16;line-height: 26px;">"true"</span>)<br> <span style="line-height: 26px;">List<User> <span style="color: #1c00cf;line-height: 26px;">getUserList</span><span style="color: #5c2699;line-height: 26px;">(IPage<UserDTO> userPage, @Param(<span style="color: #c41a16;line-height: 26px;">"query"</span>)</span> UserQuery query)</span>;<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这样调用<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">getUserList()</code>不再会加多租户过滤条件了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">通过上面我们知道了这个多租户插件其实就是通过解析SQL,然后进行拼接多租户id过滤条件来实现SQL增强从而做到数据隔离,解析SQL的框架叫:<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">JSqlParser</code>,官方文档:https://github.com/JSQLParser/JSqlParser/wiki,之前我总结过一篇关于<a href="https://mp.weixin.qq.com/s?__biz=Mzg5MDY1NzI0MQ==&mid=2247484705&idx=1&sn=5c344c3f3d4aa426976ec2513dab3adb&chksm=cfd80597f8af8c8156c29286995ca400de1a50c9032a5b64b512623aa83c3ebb4cc8b39ae0bc&token=1707825582&lang=zh_CN&scene=21#wechat_redirect" style="color: rgb(248, 57, 41);border-bottom: 1px solid rgb(248, 57, 41);" data-linktype="2"> Druid解析动态SQL</a>。Druid也可以解析SQL,我们都知道SQL语句会生成语法树,两者对SQL解析的孰强孰弱(特别是复杂SQL)不得而知,可以自行验证对比,我这里给出一个<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">JSqlParser</code>解析出错的情况,把上面的SQL语句<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">user_role r</code> 改为 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">user_role ur</code></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQccdCenu6ia845wTA3XgZ9RhjniclKHdohqH5srY3xFPQfUIAQzEySOrHUmCNDpCIxK5XrtichXV9Dib/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #aa0d91;line-height: 26px;">select</span> u.* <span style="color: #aa0d91;line-height: 26px;">from</span> <span style="color: #aa0d91;line-height: 26px;">user</span> u<br> <span style="color: #aa0d91;line-height: 26px;">left</span> <span style="color: #aa0d91;line-height: 26px;">join</span> user_role ur <span style="color: #aa0d91;line-height: 26px;">on</span> u.id = ur.user_id<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">按照上面一样调用执行<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">getUserList()</code>, 会报解析错误:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQccdCenu6ia845wTA3XgZ9RhjniclKHdohqH5srY3xFPQfUIAQzEySOrHUmCNDpCIxK5XrtichXV9Dib/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;">Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Failed to process, Error SQL: select u.* from user u<br>left join user_role ur on u.id = ur.user_id<br>group by u.id<br>order by u.id desc<br>at com.baomidou.mybatisplus.core.toolkit.ExceptionUtils.mpe(ExceptionUtils.java:<span style="color: #1c00cf;line-height: 26px;">39</span>)<br>at com.baomidou.mybatisplus.extension.parser.JsqlParserSupport.parserSingle(JsqlParserSupport.java:<span style="color: #1c00cf;line-height: 26px;">52</span>)<br>at com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor.beforeQuery(TenantLineInnerInterceptor.java:<span style="color: #1c00cf;line-height: 26px;">65</span>)<br>at com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor.intercept(MybatisPlusInterceptor.java:<span style="color: #1c00cf;line-height: 26px;">78</span>)<br>at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:<span style="color: #1c00cf;line-height: 26px;">62</span>)<br>at com.sun.proxy.$Proxy178.query(Unknown Source)<br>at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:<span style="color: #1c00cf;line-height: 26px;">151</span>)<br>... <span style="color: #1c00cf;line-height: 26px;">101</span> common frames omitted<br>Caused by: net.sf.jsqlparser.parser.ParseException: Encountered unexpected token: <span style="color: #c41a16;line-height: 26px;">"ur"</span> <K_ISOLATION><br>at line <span style="color: #1c00cf;line-height: 26px;">2</span>, column <span style="color: #1c00cf;line-height: 26px;">29</span>.<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我在<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">mybatis-plus</code>的官方提了一个issue:https://github.com/baomidou/mybatis-plus/issues/5086,也得到官方维护者的迅速回应说是<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">JSqlParser</code>解析的问题,不是<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">mybatis-plus</code>的问题~~~,给出的建议就是把别名<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">ur</code>改成别的,或者升级到<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">JSqlParser</code>的最新版本。</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;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;">4.总结</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">至此,我们对多租户系统数据隔离实现方案,架构设计,以及如何优雅实现全局操作数据隔离都讲完了,同时也对的多租户插件实现原理和源码流程套路进行了浅析,也对实际应用案例中进行了举证并阐述了相关细节点。当然数据权限不止停留在租户(公司)层面上面,大多数系统的数据权限会按照业务组织架构角色来控制,数据权限其套路和根据角色判断菜单权限一回事。由于数据权限通常与公司业务相关,比较个性化,每家公司业务组织架构不尽相同,所以实际开发项目的数据权限隔离还需要大家按实际需求进行修改,但总的来说我们可以模仿多租户隔离实现方式,比如说一个业务系统组织架构有公司(org_id),公司下有多个部门(dept_id),部门下有多个团队分组(team_id),团队下有多个人员(user_id)。不同角色只能看到不同数据,部门经理只能看到自己部门的数据,小组长只能看到自己小组的数据,这些实现逻辑套路都可以模仿多租户插件的方式进行优雅实现,这也是我后面有时间想研究的,后续会再出一篇数据权限的实现方案总结。</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);border-left-width: 2px;padding: 8px 10px 8px 15px;background: rgb(255, 249, 249);border-left-color: rgb(239, 112, 96);margin-top: 0px;margin-bottom: 20px;letter-spacing: 0.5444px;"></blockquote> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"></figure> </section>
作者:微信小助手
<section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MjM5MjMzMjE4MA==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/6tHzAJyhInBu9LYLryBFteHVfsYqZ7VHoK13sGsRd0LhBI1WxsusXgWXqZsU3yic2vTnSnbCpMPRnN2T1T1vVsw/0?wx_fmt=png" data-nickname="UX设计精选" data-alias="UEUXbest" data-signature="精选用户体验、交互设计文章,分享行业动态和工具资源。" data-from="0" data-is_biz_ban="0"></mp-common-profile> </section> <section data-darkmode-bgcolor-16444203398483="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16444203398483="#fff|rgb(255, 255, 255)" data-darkmode-color-16444203398483="rgb(163, 163, 163)" data-darkmode-original-color-16444203398483="#fff|rgb(163, 163, 163)" data-style="margin: 5px 10px 10px; outline: 0px; max-width: 100%; font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255); min-height: 1em; caret-color: rgb(51, 51, 51); text-size-adjust: auto; line-height: 1.75em; letter-spacing: 0.5px; visibility: visible; box-sizing: border-box !important; overflow-wrap: break-word !important; color: rgb(163, 163, 163) !important;" style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);min-height: 1em;caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"> <span style="font-size: 16px;"><span data-darkmode-bgcolor-16444203398483="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16444203398483="#fff|rgb(255, 255, 255)" data-darkmode-color-16444203398483="rgb(157, 157, 157)" data-darkmode-original-color-16444203398483="#fff|rgb(163, 163, 163)|rgb(73, 73, 73)" data-style="outline: 0px; max-width: 100%; color: rgb(73, 73, 73); font-family: PingFangSC-Light; font-size: 15px; letter-spacing: 1px; text-indent: 0em; visibility: visible; text-decoration: none; box-sizing: border-box !important; overflow-wrap: break-word !important;" style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;visibility: visible;">今天分享的是</span><strong data-darkmode-bgcolor-16444203398483="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16444203398483="#fff|rgb(255, 255, 255)" data-darkmode-color-16444203398483="rgb(163, 163, 163)" data-darkmode-original-color-16444203398483="#fff|rgb(163, 163, 163)" style="outline: 0px;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;visibility: visible;"><span data-darkmode-bgcolor-16444203398483="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16444203398483="#fff|rgb(255, 255, 255)" data-darkmode-color-16444203398483="rgb(29, 185, 84)" data-darkmode-original-color-16444203398483="#fff|rgb(163, 163, 163)|rgb(29, 185, 84)" style="outline: 0px;font-family: PingFangSC-Light;text-indent: 0em;visibility: visible;color: rgb(29, 185, 84);">「AI出图技巧</span></strong><strong data-darkmode-bgcolor-16444203398483="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16444203398483="#fff|rgb(255, 255, 255)" data-darkmode-color-16444203398483="rgb(163, 163, 163)" data-darkmode-original-color-16444203398483="#fff|rgb(163, 163, 163)" style="outline: 0px;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;visibility: visible;"><span data-darkmode-bgcolor-16444203398483="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16444203398483="#fff|rgb(255, 255, 255)" data-darkmode-color-16444203398483="rgb(29, 185, 84)" data-darkmode-original-color-16444203398483="#fff|rgb(163, 163, 163)|rgb(29, 185, 84)" style="outline: 0px;font-family: PingFangSC-Light;text-indent: 0em;visibility: visible;color: rgb(29, 185, 84);">」</span></strong><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;visibility: visible;">。</span></span> </section> <p style="margin: 5px 10px 10px;white-space: normal;outline: 0px;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;font-size: 16px;">AI生成的作品虽视觉效果很棒,但容易出现每个人都会遇到的<strong>痛点问题</strong>:脑海里预想的效果和AI生成出来的往往落差很大,而且反复重新生成好多次仍达不到想要的效果。</span> <o:p></o:p></p> <p style="margin: 5px 10px 10px;white-space: normal;outline: 0px;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="font-size: 16px;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">这是一套官方通用的描述模板,不一定每个类型都会设定,但</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;background-color: rgb(255, 248, 149);">输入顺序</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">大概是这样:</span><span style="color: rgb(73, 73, 73);font-family: PingFangSC-Light;text-indent: 0em;">「主体、情境、道具、气氛、风格、艺术家名字、色彩、光照、特效、精致度、镜头焦段、渲染引擎、参考网站、指令」,面对这么长的描述模板,很容易把用户劝退。</span></span></p> <section style="margin: 5px 10px 48px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"> <span style="font-size: 16px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;text-indent: 0em;">那怎么才能用尽可能少的描述,让<strong>AI</strong>知道你想要什么呢?这里总结<strong>6个</strong>用在Midjourney AI出图上最有效的技巧!</span> </section> <h2 style="margin: 5px 10px 16px;outline: 0px;font-size: 17px;white-space: normal;clear: both;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span data-darkmode-bgcolor-16400227386269="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16400227386269="#fff|rgb(255, 255, 255)" data-darkmode-bgcolor-16444203398483="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16444203398483="#fff|rgb(255, 255, 255)" data-darkmode-color-16444203398483="rgb(157, 157, 157)" data-darkmode-original-color-16444203398483="#fff|rgb(163, 163, 163)|rgb(73, 73, 73)" data-style="outline: 0px; max-width: 100%; color: rgb(73, 73, 73); font-family: PingFangSC-Light; font-size: 15px; text-indent: 0em; visibility: visible; box-sizing: border-box !important; overflow-wrap: break-word !important;" style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;font-size: 15px;text-indent: 0em;visibility: visible;"><span style="outline: 0px;text-indent: 0em;letter-spacing: 1px;visibility: visible;"><strong style="outline: 0px;letter-spacing: 0.5px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;visibility: visible;"><span lang="EN-US" style="outline: 0px;font-weight: 400;color: rgb(163, 163, 163);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: center;font-size: 20px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.5px;background-color: rgb(29, 185, 84);font-size: 18px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"> </span></strong></span><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.5px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"> </span></strong></span></span></strong></span></strong></span><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 20px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;text-indent: 0em;visibility: visible;color: rgb(73, 73, 73);font-family: PingFangSC-Light;">使用肯定描述</span></strong></span></span></h2> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="font-size: 16px;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">Midjourney目前不是特别懂否定的描述词,尽量不要用</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;background-color: rgb(255, 248, 149);">not、but、except、without</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">等否定词,失败率会变高。</span></span> <o:p></o:p></p> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;font-size: 16px;">因为描述词里有提到的某个关键词时,AI就很可能画出来,忽略否定的逻辑关系。</span> <o:p></o:p></p> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="font-size: 16px;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">例如想生成猫的图片,避免用「not black cat」,改用</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;background-color: rgb(255, 248, 149);">「pink cat」</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">。</span></span> <o:p></o:p></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 16px;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.5212962962962963" data-s="300,640" src="/upload/d4caab7cf0ea7bff89c5e3f0617b2a64.jpg" data-type="jpeg" data-w="1080" style=""></p> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="font-size: 16px;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">例如想生成一个看起来像兔子的猫,避免用「a cat but looks like a rabbit」,改用</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;background-color: rgb(255, 248, 149);">「a cat like a rabbit」</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">,会更精准。</span></span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 48px;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.5212962962962963" data-s="300,640" src="/upload/f88d3461821eb9b610cc6ba395fe7068.jpg" data-type="jpeg" data-w="1080" style=""></p> <h2 style="margin: 5px 10px 16px;font-size: 17px;white-space: normal;outline: 0px;clear: both;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span data-darkmode-bgcolor-16400227386269="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16400227386269="#fff|rgb(255, 255, 255)" data-darkmode-bgcolor-16444203398483="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16444203398483="#fff|rgb(255, 255, 255)" data-darkmode-color-16444203398483="rgb(157, 157, 157)" data-darkmode-original-color-16444203398483="#fff|rgb(163, 163, 163)|rgb(73, 73, 73)" data-style="outline: 0px; max-width: 100%; color: rgb(73, 73, 73); font-family: PingFangSC-Light; font-size: 15px; text-indent: 0em; visibility: visible; box-sizing: border-box !important; overflow-wrap: break-word !important;" style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;font-size: 15px;text-indent: 0em;visibility: visible;"><span style="outline: 0px;text-indent: 0em;letter-spacing: 1px;visibility: visible;"><strong style="outline: 0px;letter-spacing: 0.5px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;visibility: visible;"><span lang="EN-US" style="outline: 0px;font-weight: 400;color: rgb(163, 163, 163);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: center;font-size: 20px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.5px;background-color: rgb(29, 185, 84);font-size: 18px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"> </span></strong></span><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.5px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"> </span></strong></span></span></strong></span></strong></span><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 20px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;text-indent: 0em;visibility: visible;color: rgb(73, 73, 73);font-family: PingFangSC-Light;">清楚说明你想要什么</span></strong></span></span></h2> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="font-size: 16px;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">对比抽象的描述词,尽量具体地描述图像。抽象的描述词会让画面超出预期</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;background-color: rgb(255, 248, 149);">很难控制</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">,越具象越精准。</span></span> <o:p></o:p></p> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="font-size: 16px;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">比较抽象的词包括:</span><span style="color: rgb(73, 73, 73);font-family: PingFangSC-Light;text-indent: 0em;">期待、梦、实用、概念、意义、想像、经验、记忆、论点、叙述、友情、使命、压力、人生、智慧…</span></span></p> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="font-size: 16px;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">例如想生成猫咪开会的图片,我们想要的场景肯定是一群在开会的猫,而不是人们在开会的时候会议室里有只猫,因此避免用「cat in meeting」,改用</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;background-color: rgb(255, 248, 149);">「3 cats chatting」</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">。</span></span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 48px;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.5342592592592592" data-s="300,640" src="/upload/45260cfdb9943128a53de3ae41a0165d.jpg" data-type="jpeg" data-w="1080" style=""></p> <h2 style="margin: 5px 10px 16px;font-size: 17px;white-space: normal;outline: 0px;clear: both;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span data-darkmode-bgcolor-16400227386269="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16400227386269="#fff|rgb(255, 255, 255)" data-darkmode-bgcolor-16444203398483="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16444203398483="#fff|rgb(255, 255, 255)" data-darkmode-color-16444203398483="rgb(157, 157, 157)" data-darkmode-original-color-16444203398483="#fff|rgb(163, 163, 163)|rgb(73, 73, 73)" data-style="outline: 0px; max-width: 100%; color: rgb(73, 73, 73); font-family: PingFangSC-Light; font-size: 15px; text-indent: 0em; visibility: visible; box-sizing: border-box !important; overflow-wrap: break-word !important;" style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;font-size: 15px;text-indent: 0em;visibility: visible;"><span style="outline: 0px;text-indent: 0em;letter-spacing: 1px;visibility: visible;"><strong style="outline: 0px;letter-spacing: 0.5px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;visibility: visible;"><span lang="EN-US" style="outline: 0px;font-weight: 400;color: rgb(163, 163, 163);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: center;font-size: 20px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.5px;background-color: rgb(29, 185, 84);font-size: 18px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"> </span></strong></span><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.5px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"> </span></strong></span></span></strong></span></strong></span><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 20px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;text-indent: 0em;visibility: visible;color: rgb(73, 73, 73);font-family: PingFangSC-Light;">太细碎的细节可能无法精准表达</span></strong></span></span></h2> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;font-size: 16px;">AI不一定了解「事物之间的关系」,所以可以试着重复描述词、更改描述词的顺序、重复元素或添加更多细节。但细节太多AI会更容易混淆。</span> <o:p></o:p></p> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="font-size: 16px;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">例如想生成一群猫跳舞的场景,避免用「3 black cats in tutus dance around the altar on the top floor of a sun-baked building to pray for rain」,改用</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;background-color: rgb(255, 248, 149);">「3 black cats in tutus dancing on the top floor」</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">。</span></span> <o:p></o:p></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 48px;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.5611111111111111" data-s="300,640" src="/upload/8d8ddbb160c6412e3723ac6576fb54be.jpg" data-type="jpeg" data-w="1080" style=""></p> <h2 style="margin: 5px 10px 16px;font-size: 17px;white-space: normal;outline: 0px;clear: both;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span data-darkmode-bgcolor-16400227386269="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16400227386269="#fff|rgb(255, 255, 255)" data-darkmode-bgcolor-16444203398483="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16444203398483="#fff|rgb(255, 255, 255)" data-darkmode-color-16444203398483="rgb(157, 157, 157)" data-darkmode-original-color-16444203398483="#fff|rgb(163, 163, 163)|rgb(73, 73, 73)" data-style="outline: 0px; max-width: 100%; color: rgb(73, 73, 73); font-family: PingFangSC-Light; font-size: 15px; text-indent: 0em; visibility: visible; box-sizing: border-box !important; overflow-wrap: break-word !important;" style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;font-size: 15px;text-indent: 0em;visibility: visible;"><span style="outline: 0px;text-indent: 0em;letter-spacing: 1px;visibility: visible;"><strong style="outline: 0px;letter-spacing: 0.5px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;visibility: visible;"><span lang="EN-US" style="outline: 0px;font-weight: 400;color: rgb(163, 163, 163);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: center;font-size: 20px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.5px;background-color: rgb(29, 185, 84);font-size: 18px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"> </span></strong></span><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.5px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"> </span></strong></span></span></strong></span></strong></span><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 20px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;text-indent: 0em;visibility: visible;color: rgb(73, 73, 73);font-family: PingFangSC-Light;">尽量使用特定数量</span></strong></span></span></h2> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;font-size: 16px;">之前提到描述越具体越好,用具体的数字指明数量也比用「many」更好。</span> <o:p></o:p></p> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="font-size: 16px;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">例如避免用「many cats」,改用</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;background-color: rgb(255, 248, 149);">「8 cats playing together」</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">。</span></span> <o:p></o:p></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 16px;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.5287037037037037" data-s="300,640" src="/upload/b68966e3b19174806de7b37856bc3a24.jpg" data-type="jpeg" data-w="1080" style=""></p> <section style="margin: 5px 10px 48px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"> <span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;font-size: 16px;">有兴趣的可以亲自试试输入「cat mountain cat sea」,看看是否是你想要的那种「猫山猫海」的效果hh。</span> <o:p></o:p> </section> <h2 style="margin: 5px 10px 16px;font-size: 17px;white-space: normal;outline: 0px;clear: both;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span data-darkmode-bgcolor-16400227386269="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16400227386269="#fff|rgb(255, 255, 255)" data-darkmode-bgcolor-16444203398483="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16444203398483="#fff|rgb(255, 255, 255)" data-darkmode-color-16444203398483="rgb(157, 157, 157)" data-darkmode-original-color-16444203398483="#fff|rgb(163, 163, 163)|rgb(73, 73, 73)" data-style="outline: 0px; max-width: 100%; color: rgb(73, 73, 73); font-family: PingFangSC-Light; font-size: 15px; text-indent: 0em; visibility: visible; box-sizing: border-box !important; overflow-wrap: break-word !important;" style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;font-size: 15px;text-indent: 0em;visibility: visible;"><span style="outline: 0px;text-indent: 0em;letter-spacing: 1px;visibility: visible;"><strong style="outline: 0px;letter-spacing: 0.5px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;visibility: visible;"><span lang="EN-US" style="outline: 0px;font-weight: 400;color: rgb(163, 163, 163);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: center;font-size: 20px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.5px;background-color: rgb(29, 185, 84);font-size: 18px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"> </span></strong></span><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.5px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"> </span></strong></span></span></strong></span></strong></span><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 20px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;text-indent: 0em;visibility: visible;color: rgb(73, 73, 73);font-family: PingFangSC-Light;">避免延伸联想的概念</span></strong></span></span></h2> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;font-size: 16px;">使用AI生成图片时,经常遇到的一个情况是不是图片生成不出来,而是生成的图总觉得少了点东西,没有达到预想的感觉。</span> <o:p></o:p></p> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="font-size: 16px;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">这个时候需要检查自己写的描述词是否要</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;background-color: rgb(255, 248, 149);">延伸联想</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">。因为不管输入什么关键词,Midjourney都能出图,但生成的图像是不是和自己想要一样是两回事。</span></span> <o:p></o:p></p> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="font-size: 16px;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">例如避免用「Alien Cultures in the Multiverse」,改用</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;background-color: rgb(255, 248, 149);">「Sci-fi Alien Workstation」</span><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">。</span></span> <o:p></o:p></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 48px;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.5296296296296297" data-s="300,640" src="/upload/ed8851ccf39b23e7e1e86faed2e4715a.jpg" data-type="jpeg" data-w="1080" style=""></p> <h2 style="margin: 5px 10px 16px;font-size: 17px;white-space: normal;outline: 0px;clear: both;min-height: 1em;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span data-darkmode-bgcolor-16400227386269="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16400227386269="#fff|rgb(255, 255, 255)" data-darkmode-bgcolor-16444203398483="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16444203398483="#fff|rgb(255, 255, 255)" data-darkmode-color-16444203398483="rgb(157, 157, 157)" data-darkmode-original-color-16444203398483="#fff|rgb(163, 163, 163)|rgb(73, 73, 73)" data-style="outline: 0px; max-width: 100%; color: rgb(73, 73, 73); font-family: PingFangSC-Light; font-size: 15px; text-indent: 0em; visibility: visible; box-sizing: border-box !important; overflow-wrap: break-word !important;" style="color: rgb(73, 73, 73);font-family: PingFangSC-Light;font-size: 15px;outline: 0px;text-indent: 0em;letter-spacing: 1px;visibility: visible;"><strong style="outline: 0px;letter-spacing: 0.5px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;visibility: visible;"><span lang="EN-US" style="outline: 0px;font-weight: 400;color: rgb(163, 163, 163);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: center;font-size: 20px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.5px;background-color: rgb(29, 185, 84);font-size: 18px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"> </span></strong></span><span style="outline: 0px;color: rgb(163, 163, 163);font-family: -apple-system, "system-ui", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.5px;visibility: visible;"><strong style="outline: 0px;visibility: visible;"><span style="outline: 0px;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;"> </span></strong></span></span></strong></span></strong></span><strong style="font-size: 20px;text-indent: 0em;outline: 0px;visibility: visible;"><span style="outline: 0px;text-indent: 0em;visibility: visible;color: rgb(73, 73, 73);font-family: PingFangSC-Light;">活用翻译软件</span></strong></h2> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="font-size: 16px;"><span style="font-size: 16px;outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">英文不好没关系,可以</span><span style="font-size: 16px;outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;background-color: rgb(255, 248, 149);">用翻译软件</span><span style="font-size: 16px;outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">输入中文、复制英文贴到Midjourney里。</span></span> <o:p></o:p></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 16px;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.30277777777777776" data-s="300,640" src="/upload/ed8455aa644ee417ee1a8f26c6864c38.png" data-type="png" data-w="1080" style=""></p> <p style="margin: 5px 10px 10px;outline: 0px;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="font-size: 16px;"><span style="font-size: 16px;outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">输入描述词时,不用过度考虑描述词的</span><span style="font-size: 16px;outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;background-color: rgb(255, 248, 149);">语法问题</span><span style="font-size: 16px;outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;visibility: visible;">,因为AI更关注描述词的内容,而非描述词的语法问题。</span></span> <o:p></o:p></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 48px;"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.80078125" data-s="300,640" src="/upload/83584faaafb44f60cd8ed55ccdd5c337.jpg" data-type="jpeg" data-w="1024" style=""></p> <p style="margin: 5px 10px 10px;outline: 0px;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;font-size: 15px;"><strong style="outline: 0px;color: rgb(29, 185, 84);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;"><span data-darkmode-bgcolor-16444203398483="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16444203398483="#fff|rgb(255, 255, 255)" data-darkmode-color-16444203398483="rgb(157, 157, 157)" data-darkmode-original-color-16444203398483="#fff|rgb(163, 163, 163)|rgb(73, 73, 73)" data-style="outline: 0px; max-width: 100%; color: rgb(73, 73, 73); font-family: PingFangSC-Light; font-size: 15px; letter-spacing: 1px; text-indent: 0em; visibility: visible; text-decoration: none; box-sizing: border-box !important; overflow-wrap: break-word !important;" style="outline: 0px;font-size: 18px;font-family: PingFangSC-Light;letter-spacing: 1px;text-indent: 0em;visibility: visible;">最后</span></strong></span></p> <p style="margin: 5px 10px 10px;outline: 0px;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;caret-color: rgb(51, 51, 51);text-size-adjust: inherit;line-height: 1.75em;letter-spacing: 0.5px;visibility: visible;color: rgb(163, 163, 163) !important;"><span style="outline: 0px;text-indent: 0em;color: rgb(73, 73, 73);font-family: PingFangSC-Light;letter-spacing: 0.5px;caret-color: rgb(51, 51, 51);background-color: rgb(255, 255, 255);font-size: 16px;">以上6个小技巧,肯定能帮助你在描述等关键词时,让AI更精准Get到你的想法!</span></p>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;overflow-wrap: break-word;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;line-height: 1.6;word-break: break-word;text-align: left;font-size: 15px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;visibility: visible;box-sizing: border-box !important;"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="text-wrap: wrap;line-height: 1.6;word-break: break-word;text-align: left;font-size: 15px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;"> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">这次我们来聊下如何<span style="color: rgb(255, 41, 65);">一键部署分支代码到服务器</span>。</p> <section> <span style="letter-spacing: 0.8px;word-spacing: 0.8px;">本文主要内容如下:</span> <br> </section> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;"><span role="listitem" data-ref="n191" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"><span role="listitem" data-ref="n191" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"><span style="word-spacing: 0.85px;">背景</span></span><span role="listitem" data-ref="n229" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;">Jenkins 简易安装教程</span><span role="listitem" data-ref="n236" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;">配置 Jenkins</span><span role="listitem" data-ref="n250" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;">通过 Jenkins 一键部署</span><span role="listitem" data-ref="n266" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 创建一个项目</span><span role="listitem" data-ref="n271" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 配置拉取的代码仓库</span><span role="listitem" data-ref="n278" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 配置打包</span><span role="listitem" data-ref="n282" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 运行项目</span><span role="listitem" data-ref="n292" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 拷贝安装包</span><span role="listitem" data-ref="n293" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 安装插件</span><span role="listitem" data-ref="n310" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 备份服务器 JAR 包</span><span role="listitem" data-ref="n321" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 拷贝 JAR 包到远程服务器</span><span role="listitem" data-ref="n337" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 滚动更新服务</span><span role="listitem" data-ref="n343" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 远程服务器上创建脚本</span><span role="listitem" data-ref="n348" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 部署</span><span role="listitem" data-ref="n352" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 遇到的问题</span><span role="listitem" data-ref="n353" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 问题 1、添加 Git 仓库时,无法访问</span><span role="listitem" data-ref="n358" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 问题 2</span><span role="listitem" data-ref="n363" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 问题 3</span><span role="listitem" data-ref="n366" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 解决方案</span><span role="listitem" data-ref="n368" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 解决思路</span><span role="listitem" data-ref="n370" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 问题 4:could not identify password for [xxx]</span><span role="listitem" data-ref="n372" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"> 问题 5:ssh 超时配置</span></span><span role="listitem" data-ref="n372" style="display: block;color: rgb(65, 131, 196);font-family: "Source Sans Pro", "等距更纱黑体 SC", "Helvetica Neue", Arial, sans-serif;font-size: 15.3px;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;"></span></p> <h2 data-tool="mdnice编辑器" style="margin-top: 20px;margin-right: 10px;font-weight: bold;font-size: 22px;color: black;"><span style="padding-left: 10px;font-size: 18px;color: rgb(34, 34, 34);display: inline-block;border-left: 5px solid rgb(248, 57, 41);">背景</span></h2> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">新项目没有完善的部署流程,只能自己先搭一套来顶一顶了。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">服务器资源如下:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.2833333333333333" src="/upload/9ba62e57d49a25913c5dc1f66bb3c374.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">原理图如下所示:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.7861111111111111" src="/upload/3396dd27677cc5fd13d9eadc155c5d8d.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> Jenkins 打包部署原理图 </figcaption> </figure> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;width: 577.422px;color: rgb(248, 57, 41);font-size: 16px;"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Jenkins 部署在一台服务器上,然后安装了很多必备的 Jenkins 插件。比如拉取 Gitlab 仓库代码的插件、远程执行命令和拷贝文件的插件。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Jenkins 开始运行一个任务时,通过 Git 插件从 Gitlab 仓库拉取代码到本地目录。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Jenkins 通过 JDK 和 Maven 工具对 Java 代码进行打包部署。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Jenkins 通过 SSH 插件执行远程命令,将包进行备份、清理操作。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Jenkins 将 JAR 包拷贝到远程服务器的固定目录下。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Jenkins 执行远程命令,更新服务。 </section></li> </ul> <h2 data-tool="mdnice编辑器" style="margin-top: 20px;margin-right: 10px;font-weight: bold;font-size: 22px;color: black;"><span style="padding-left: 10px;font-size: 18px;color: rgb(34, 34, 34);display: inline-block;border-left: 5px solid rgb(248, 57, 41);">Jenkins 简易安装教程</span></h2> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">Jenkins 官方网站对 Jenkins 如何安装已经讲解得非常清晰了,所以这里不再赘述,贴一下官方网站,自行去看吧。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">Jenkins 下载地址:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/ibKHP1TZZeXL1oiaVUBdfxCd7bf6iaKW5z9qekDUC90N9QdGOBibibD2WcJbWkUeUztPUrxGacwUOFAfNtmMha5GQ0ZhFUjRQibfvz/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 578px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;">https://www.jenkins.io/download/<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">Jenkins 安装步骤:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/ibKHP1TZZeXL1oiaVUBdfxCd7bf6iaKW5z9qekDUC90N9QdGOBibibD2WcJbWkUeUztPUrxGacwUOFAfNtmMha5GQ0ZhFUjRQibfvz/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 578px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;">https://www.jenkins.io/doc/book/installing/<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">安装完成后,我们需要配置 Jenkins。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 20px;margin-right: 10px;font-weight: bold;font-size: 22px;color: black;"><span style="padding-left: 10px;font-size: 18px;color: rgb(34, 34, 34);display: inline-block;border-left: 5px solid rgb(248, 57, 41);">配置 Jenkins</span></h2> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">因为我们要打包部署的项目是 Java 项目,所以需要将 Java JDK 所在的目录和 Maven 所在目录配置到 Jenkins 中,这样 Jenkins 打包时就能利用这两个工具进行打包。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">配置全局工具:Maven</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">配置如下:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.5157407407407407" src="/upload/a31561bdf5d49b36268af7bc73c69cc.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> Jenkins配置入口 </figcaption> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="1.412037037037037" src="/upload/5df84329a43ed9658be9469337ad0ec0.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> Jenkins Global Tool Configuration </figcaption> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">配置环境变量:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;width: 577.422px;color: rgb(248, 57, 41);font-size: 16px;"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Java JDK </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Maven </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.9185185185185185" src="/upload/fb4f7b23d37c58b1e86d1eafb4103c48.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 全局属性配置 </figcaption> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">上面的配置完成后,我们就可以测试下是否可以将代码仓库中的某个分支的代码拉取下来进行打包。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 20px;margin-right: 10px;font-weight: bold;font-size: 22px;color: black;"><span style="padding-left: 10px;font-size: 18px;color: rgb(34, 34, 34);display: inline-block;border-left: 5px solid rgb(248, 57, 41);">通过 Jenkins 一键部署</span></h2> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">在使用 Jenkins 时,我们必须创建一个任务才行,然后这个任务里面可以配置要执行的各种操作。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">Jenkins中自动构建项目的类型有很多,常用的有以下三种:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;width: 577.422px;color: rgb(248, 57, 41);font-size: 16px;"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 自由风格软件项目(FreeStyle Project) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Maven项目(Maven Project) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 流水线项目(Pipeline Project) </section></li> </ul> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">每种类型的构建其实都可以完成一样的构建过程与结果,只是在操作方式、灵活度等方面有所区别,在</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">实际开发中可以根据自己的需求和习惯来选择。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">下面演示创建一个简单的自由风格项目来完成项目的集成过程:</p> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding: 10px 10px 10px 20px;border-left-color: rgb(255, 177, 27);color: rgb(106, 115, 125);font-size: 0.9em;border-top: none;border-right: none;border-bottom: none;overflow: auto;background: rgb(255, 245, 227);"> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 15px;color: black;line-height: 26px;">拉取代码->编译 Java 项目->备份服务器 JAR 包->删除服务器 JAR 包->拷贝 JAR 包到服务器->更新服务。</p> </blockquote> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.555878084179971" src="/upload/6578f942d5d18ec8e057c660430a7e97.png" data-type="png" data-w="689" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">创建一个项目</span></h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.7518518518518519" src="/upload/17d0c4240345c5a542b39d62c1668ea3.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 创建一个项目 </figcaption> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">创建成功后就会出现一条记录:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.29444444444444445" src="/upload/ac2a017d43f62d9a41bc3609e0f12990.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> Dashboard 界面 </figcaption> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">为了测试我们的 Jenkins 是否能正常拉取代码并打包,我们需要配置 Gitlab 代码仓库的地址、用户名、密码。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: black;"><span style="font-size: 15px;color: rgb(34, 34, 34);">配置拉取的代码仓库</span></h4> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;width: 577.422px;color: rgb(248, 57, 41);font-size: 16px;"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 仓库 URL </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 用户名和密码 </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.9546296296296296" src="/upload/6c34fb34b8e188604e5f9250354fe8a0.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 配置拉取的代码仓库地址和认证方式 </figcaption> </figure> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: black;"><span style="font-size: 15px;color: rgb(34, 34, 34);">配置打包</span></h4> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.7719821162444114" src="/upload/4a753259721b70ed6f4cac049d7245a.png" data-type="png" data-w="671" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 配置 Maven 打包 </figcaption> </figure> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/ibKHP1TZZeXL1oiaVUBdfxCd7bf6iaKW5z9qekDUC90N9QdGOBibibD2WcJbWkUeUztPUrxGacwUOFAfNtmMha5GQ0ZhFUjRQibfvz/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 578px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;"><span style="color: rgb(230, 192, 123);line-height: 26px;">echo</span> <span style="color: rgb(152, 195, 121);line-height: 26px;">"开始打包"</span><br>mvn clean package<br><span style="color: rgb(230, 192, 123);line-height: 26px;">echo</span> <span style="color: rgb(152, 195, 121);line-height: 26px;">"打包完成"</span><br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">配置到这一步后,我们可以先验证下这些配置是否生效。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">运行项目</span></h3> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">在 Dashboard 可以看到配置完成的任务,点击 Build Now 按钮即可开始拉取代码、打包项目。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">我们还可以从控制台输出看到打包记录。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">Jenkins 会从 Gitlab 仓库拉取指定分支的代码,然后运行 mvn clean package 命令,进行打包。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="1.1212962962962962" src="/upload/f4a04348e9a999c27e9b5b89f953fd3.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 打印 Jenkins 运行项目的结果 </figcaption> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">输出记录中打印出了以下关键信息:代码拉取后存放在哪,打的 jar 包在哪。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">代码和生成的 jar 包在到这个根目录找到:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/ibKHP1TZZeXL1oiaVUBdfxCd7bf6iaKW5z9qekDUC90N9QdGOBibibD2WcJbWkUeUztPUrxGacwUOFAfNtmMha5GQ0ZhFUjRQibfvz/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 578px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;">C:\ProgramData\Jenkins.jenkins\workspace\passjava-dev<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">还可以从打印日志的最后看到这次打包用时 2 min 33 秒,任务的执行状态为 Finished Success。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">接下来就是将这些 JAR 包拷贝到远程服务器地址。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">拷贝安装包</span></h3> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: black;"><span style="font-size: 15px;color: rgb(34, 34, 34);">安装插件</span></h4> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">拷贝安装包需要用到一个插件:Publish Over SSH。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">Dashboard>Manage Jenkins->插件管理->Avaliable plugins。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">下图是已经安装好了这款插件的截图。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.9157407407407407" src="/upload/3f3a3574dc7fe62b5986329a0a96e6c8.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> Jenkins 插件管理 </figcaption> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">配置这个插件的全局配置:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;width: 577.422px;color: rgb(248, 57, 41);font-size: 16px;"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> SSH Server Name:远程服务器的名字,后面在配置拷贝包的时候可以根据名字选择拷贝到哪台服务器。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Hostname:SSH Server 的 Hostname。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Username:SSH Server 登录名和密码或密钥。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Remote Directory:指定将文件拷贝到哪个目录。 </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="1.2955854126679462" src="/upload/acf18632bcbf52bdbbe57b53531daee4.png" data-type="png" data-w="1042" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 配置远程服务器地址 </figcaption> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">备份服务器 JAR 包</span></h3> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">在上传打包好的 JAR 包之前,需要将应用服务器上的 JAR 备份。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">备份的步骤如下:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;width: 577.422px;color: rgb(248, 57, 41);font-size: 16px;"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 在远程服务器创建一个备份目录 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">bak</code>。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 在备份目录 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">bak</code>上创建一个以当前时间作为目录名的目录。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 将远程服务器的上 JAR 重命名为原文件名+时间戳的名字。 </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.9805555555555555" src="/upload/5ccb2490b16511f938091acd32c3c79a.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 备份服务器 JAR 包 </figcaption> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">拷贝 JAR 包到远程服务器</span></h3> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">需要配置以下内容:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;width: 577.422px;color: rgb(248, 57, 41);font-size: 16px;"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> SSH Server:指定要将文件拷贝到哪个服务器,格式为 <用户名>@<ip 地址>。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Transfer Set Source files:jenkins 编译后的 JAR 地址。通过之前的编译信息我们知道,JAR 包地址在如下路径: </section></li> </ul> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/ibKHP1TZZeXL1oiaVUBdfxCd7bf6iaKW5z9qekDUC90N9QdGOBibibD2WcJbWkUeUztPUrxGacwUOFAfNtmMha5GQ0ZhFUjRQibfvz/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 578px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;">C:\ProgramData\Jenkins.jenkins\workspace<Jenkins 任务名><编译目录><br></code></pre> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;width: 577.422px;color: rgb(248, 57, 41);font-size: 16px;"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Remove prefix:要移除的文件路径前缀。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Remte directory:拷贝到哪个路径下,如果之前已经配置过全局的文件夹,则拷贝的文件会放到 <全局文件夹>/ <remote directory=""> 之下,如果全局文件夹之下没有这个 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">Remote directory</code> 目录,则创建一个。这里我们不需要配置,全局配置已经可以满足条件了。 </remote> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 如果还有其他 JAR 包也需要拷贝则需要再添加一项。 </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="1.0851851851851853" src="/upload/66b061feef16ee0f3e2568dbd652b33.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 拷贝多个 JAR 包到远程服务器 </figcaption> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">滚动更新服务</span></h3> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">项目采用的 Docker Swarm 方式来管理集群中的微服务。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">Jenkins 通过 插件 发送命令到应用服务器上执行指定的脚本</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.899074074074074" src="/upload/8f33b7ace029dbcff4d36b06ad6a2ae.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 配置远程执行脚本的命令 </figcaption> </figure> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/ibKHP1TZZeXL1oiaVUBdfxCd7bf6iaKW5z9qekDUC90N9QdGOBibibD2WcJbWkUeUztPUrxGacwUOFAfNtmMha5GQ0ZhFUjRQibfvz/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 578px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;"><span style="color: rgb(230, 192, 123);line-height: 26px;">echo</span> <span style="color: rgb(152, 195, 121);line-height: 26px;">"部署 jar 包"</span><br><span style="color: rgb(230, 192, 123);line-height: 26px;">cd</span> /nfs-data/wukong/<br>nohup sudo sh restart.sh<br><span style="color: rgb(230, 192, 123);line-height: 26px;">exit</span><br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">这个命令使用 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">nohup</code> 和 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">sudo</code> 权限来执行名为 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">restart.sh</code> 的脚本。<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">nohup</code> 命令用于将脚本在后台运行,即使终端会话结束,脚本仍然继续运行。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">远程服务器上创建脚本</span></h3> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">如果想要 jenkins 执行远程服务器上的脚本,则需要先在远程服务器上创建一个可执行的脚本。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">这里我们需要重启服务器的容器服务,所以在这个目录 /nfs-data/wukong/ 编写一个 restart.sh 脚本。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/ibKHP1TZZeXL1oiaVUBdfxCd7bf6iaKW5z9qekDUC90N9QdGOBibibD2WcJbWkUeUztPUrxGacwUOFAfNtmMha5GQ0ZhFUjRQibfvz/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 578px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;"><span style="color: rgb(230, 192, 123);line-height: 26px;">echo</span> <span style="color: rgb(152, 195, 121);line-height: 26px;">"部署 passjava 服务"</span><br>nohup sudo docker service update accountservice --force > /nfs-data/wukong/jenkins/account.txt<br>nohup sudo docker service update gatewayservice --force > /nfs-data/wukong/jenkins/gateway.txt<br>nohup sudo docker service update qmsservice --force > /nfs-data/wukong/jenkins/qms.txt<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">这个命令使用<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">--force</code>选项来更新名为"accountservice、gatewayservice、qmsservice"的 Docker 服务。命令的输出被重定向到文件<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">/nfs-data/wukong/jenkins/xxx.txt</code>中。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">部署</span></h3> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">再次测试是否能正确编译代码,上传 jar 包,部署微服务。</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">部署结果如下:<span style="font-weight: 700;color: rgb(248, 57, 41);">Finished: SUCESS</span></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.31203703703703706" src="/upload/7e3d0fe85fbc8d7640c64e13c3a6fd9d.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 部署结果 </figcaption> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 20px;margin-right: 10px;font-weight: bold;font-size: 22px;color: black;"><span style="padding-left: 10px;font-size: 18px;color: rgb(34, 34, 34);display: inline-block;border-left: 5px solid rgb(248, 57, 41);">遇到的问题</span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">问题 1、添加 Git 仓库时,无法访问</span></h3> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">SSL certificate problem: unable to get local issuer certificate</p> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">解决方案:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/ibKHP1TZZeXL1oiaVUBdfxCd7bf6iaKW5z9qekDUC90N9QdGOBibibD2WcJbWkUeUztPUrxGacwUOFAfNtmMha5GQ0ZhFUjRQibfvz/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 578px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;">git config --system http.sslVerify <span style="color: rgb(86, 182, 194);line-height: 26px;">false</span><br><br>git config --global http.sslVerify <span style="color: rgb(86, 182, 194);line-height: 26px;">false</span><br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">参考链接:https://stackoverflow.com/questions/39746535/jenkins-git-ssl-certificate-error</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">问题 2</span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/ibKHP1TZZeXL1oiaVUBdfxCd7bf6iaKW5z9qekDUC90N9QdGOBibibD2WcJbWkUeUztPUrxGacwUOFAfNtmMha5GQ0ZhFUjRQibfvz/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 578px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;">stderr: fatal: unable to access <span style="color: rgb(152, 195, 121);line-height: 26px;">'url of my git/'</span>: SSL certificate problem: self signed certificate <span style="color: rgb(198, 120, 221);line-height: 26px;">in</span> certificate chain<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">解决方案:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/ibKHP1TZZeXL1oiaVUBdfxCd7bf6iaKW5z9qekDUC90N9QdGOBibibD2WcJbWkUeUztPUrxGacwUOFAfNtmMha5GQ0ZhFUjRQibfvz/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 578px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;">git config --system http.sslVerify <span style="color: rgb(86, 182, 194);line-height: 26px;">false</span><br><br>git config --global http.sslVerify <span style="color: rgb(86, 182, 194);line-height: 26px;">false</span><br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">参考链接:https://stackoverflow.com/questions/39746535/jenkins-git-ssl-certificate-error</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">问题 3</span></h3> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">Exception when publishing, exception message</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.3888888888888889" src="/upload/4609b707f53daa8231d382c935d4fc25.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 问题 3 的记录 </figcaption> </figure> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: black;"><span style="font-size: 15px;color: rgb(34, 34, 34);">解决方案</span></h4> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">远程机器上需要用 sudo 命令执行 docker 命令,这个时候需要输入密码,通过配置账号 xx 执行 sudo 命令不需要输入密码。</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: black;"><span style="font-size: 15px;color: rgb(34, 34, 34);">解决思路</span></h4> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="1.379241516966068" src="/upload/b07d6fd294c0b2ba6a4ee0549f853d6c.png" data-type="png" data-w="1002" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 问题 3 的解决思路 </figcaption> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">问题 4:could not identify password for [xxx]</span></h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="1.3425925925925926" src="/upload/9b11d50647b99e8b274d6a3b9ec57945.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 问题 4 解决思路 </figcaption> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: black;"><span style="font-size: 16px;color: rgb(34, 34, 34);">问题 5:ssh 超时配置</span></h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/ibKHP1TZZeXL1oiaVUBdfxCd7bf6iaKW5z9qekDUC90N9QdGOBibibD2WcJbWkUeUztPUrxGacwUOFAfNtmMha5GQ0ZhFUjRQibfvz/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 578px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;">ERROR: Exception when publishing, exception message [Exec timed out or was interrupted after 120,011 ms]<br></code></pre> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.23981481481481481" src="/upload/de36b083be7b389474e4c9006801bd9d.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 问题 5 的记录 </figcaption> </figure> <p data-tool="mdnice编辑器" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;">解决方案:修改超时时间设置</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.9287037037037037" src="/upload/6de8e82730f36e0da435bd3ec58070a1.png" data-type="png" data-w="1080" style="margin: 20px auto;border-radius: 6px;display: block;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 问题 5 的解决方案 </figcaption> </figure> </section> <section data-role="outer" label="Powered by 135editor.com" data-style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: center; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; color: rgb(255, 150, 155); font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif; font-size: 14px; background-color: rgb(255, 255, 255); box-sizing: border-box !important; overflow-wrap: break-word !important;" class="js_darkmode__212" style="margin-bottom: 0px;text-wrap: wrap;outline: 0px;background-color: rgb(255, 255, 255);color: rgb(255, 150, 155);letter-spacing: 0.544px;text-align: center;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;"> <section data-role="paragraph" style="outline: 0px;"> <section data-style="margin: 0px; padding: 0px; outline: 0px; max-width: 100%; font-size: 16px; letter-spacing: 0.544px; line-height: 25.6px; border-width: 0px; border-style: none; border-top-color: rgb(189, 189, 189); text-align: left; box-sizing: border-box !important; overflow-wrap: break-word !important;" class="js_darkmode__213" style="outline: 0px;border-width: 0px;border-style: none;border-top-color: rgb(189, 189, 189);font-size: 16px;letter-spacing: 0.544px;line-height: 25.6px;text-align: left;"> <section data-style="margin: 5px 0px; padding: 0px; outline: 0px; max-width: 100%; display: inline-block; border-top: 3px solid rgb(70, 70, 70); border-bottom: 1px solid rgb(220, 220, 220); width: 556px; box-sizing: border-box !important; overflow-wrap: break-word !important;" class="js_darkmode__214" style="margin-top: 5px;margin-bottom: 5px;outline: 0px;border-bottom: 1px solid rgb(220, 220, 220);border-top: 3px solid rgb(70, 70, 70);display: inline-block;width: 556px;"> <section style="padding-top: 5px;padding-bottom: 5px;outline: 0px;clear: both;"> <h2 data-tool="mdnice编辑器" data-style="margin: 20px 10px 0px 0px; padding: 0px; outline: 0px; font-weight: bold; font-size: 22px; max-width: 100%; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif; letter-spacing: 0.8px; word-spacing: 0.8px; background-color: rgb(255, 255, 255); color: black; box-sizing: border-box !important; overflow-wrap: break-word !important;" class="js_darkmode__215" style="margin-top: 20px;margin-right: 10px;font-weight: bold;font-size: 22px;outline: 0px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.8px;word-spacing: 0.8px;"><span data-style="margin: 0px; padding: 0px 0px 0px 10px; outline: 0px; max-width: 100%; font-size: 18px; font-weight: 700; color: rgb(34, 34, 34); display: inline-block; border-left: 5px solid rgb(248, 57, 41); box-sizing: border-box !important; overflow-wrap: break-word !important;" class="js_darkmode__216" style="padding-left: 10px;outline: 0px;color: rgb(34, 34, 34);font-size: 18px;display: inline-block;border-left: 5px solid rgb(248, 57, 41);">关于我</span></h2> <p data-tool="mdnice编辑器" data-style="margin-top: 0em; margin-bottom: 0em; padding-top: 8px; padding-bottom: 8px; outline: 0px; max-width: 100%; text-align: left; white-space: normal; color: rgb(53, 53, 53); font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif; font-size: 15px; letter-spacing: 0.8px; word-spacing: 0.8px; background-color: rgb(255, 255, 255); line-height: 1.75; box-sizing: border-box !important; overflow-wrap: break-word !important;" class="js_darkmode__217" style="margin-top: 0em;margin-bottom: 0em;padding-top: 8px;padding-bottom: 8px;outline: 0px;color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;letter-spacing: 0.8px;word-spacing: 0.8px;line-height: 1.75;">InfoQ 签约作者、蓝桥签约作者、阿里云专家博主、51CTO 红人。</p> </section> </section> </section> </section> </section> </section>