作者:微信小助手
<ne-clipboard source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <ne-clipboard source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf=""><br></span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">CPU 飙升是一个常见的问题。</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">在生产环境中,会出现由代码问题导致CPU占用很高,该如何诊断出是哪行java代码导致? 是大家的一项重要基本功,也是大家面试中的家常骗饭。</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">如果连CPU 飙升的问题都回答不清楚, 都支支吾吾, 面试就很难通过了。</span></span></p> <h2 style="font-size: 24px;line-height: 32px;margin: 21px 0 5px 0;text-align: justify;"><span leaf=""><span textstyle="" style="font-size: 20px;font-weight: bold;">CPU100%定位的两大神器</span></span></h2> <section style="text-align: center;" nodeleaf=""> <img src="/upload/903f446eba9d0876b7f19b512145ee69.png" class="rich_pages wxw-img" data-ratio="0.33505154639175255" data-s="300,640" data-type="png" data-w="970" type="block" data-imgfileid="100000563"> </section> <h2 style="font-size: 24px;line-height: 32px;margin: 21px 0 5px 0;text-align: justify;"><span leaf=""><span textstyle="" style="font-size: 16px;">想要定位到具体是哪一行的代码导致, 一般都会使用下面的两大神器</span></span></h2> <ul style="margin: 0;padding-left: 23px;" class="list-paddingleft-1"> <li><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">通常使用的jvm自带的工具jstack,</span></span></li> <li><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">还有一种就是开源神器arthas,</span></span></li> </ul> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">一般而言,arthas还有其它的功能,所以选择它多一点.</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf=""><br></span></span></p> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u349af361%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%7D%2C%22data%22%3A%22CPU%20%E9%A3%99%E5%8D%87100%25%E7%9A%84%E8%A7%A3%E5%86%B3%E6%80%9D%E8%B7%AF%22%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p><span leaf=""><span textstyle="" style="font-size: 20px;font-weight: bold;">CPU 飙升100%的解决思路</span></span><span leaf=""><span textstyle="" style="font-size: 20px;font-weight: bold;">与方法论</span></span></p> <section style="text-align: center;" nodeleaf=""> <img src="/upload/f47c9040269ca45d30d1bc86313bb243.png" class="rich_pages wxw-img" data-ratio="0.3001027749229188" data-s="300,640" data-type="png" data-w="973" type="block" data-imgfileid="100000550"> </section> <p><span leaf=""><br></span></p> <ne-clipboard source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <h2 style="font-size: 24px;line-height: 32px;margin: 21px 0 5px 0;text-align: justify;"><span leaf=""><span textstyle="" style="font-size: 20px;font-weight: bold;">使用jstack 解决CPU 100%问题实操</span></span></h2> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">使用jstack 解决CPU 100%问题,在方法论上要用到两个命令,</span></span></p> <ul style="margin: 0;padding-left: 23px;" class="list-paddingleft-1"> <li><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">top 命令查看TOP N线程,</span></span></li> <li><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">jstack命令查看堆栈信息</span></span></li> </ul> <section style="text-align: center;" nodeleaf=""> <img src="/upload/e5cef8ab4cf8da21d44bd7f99cd2b844.png" class="rich_pages wxw-img" data-ratio="0.19328703703703703" data-s="300,640" data-type="png" data-w="864" type="block" data-imgfileid="100000551"> </section> <ne-clipboard source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <h3 style="font-size: 20;line-height: 28px;margin: 16px 0 5px 0;text-align: justify;"><span style="color: rgb(30, 30, 30);background-color: rgb(212, 224, 250);"><span leaf="">1.jstack命令讲解</span></span></h3> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">命令jstack是java堆栈的跟踪工具,可以打印出程序中所有线程的堆栈信息,包括线程状态,调用栈信息,锁信息等。</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">jstack可以诊断线程死锁、内存泄漏等问题</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">命令格式: jstack [options] pid</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(106, 115, 125);background-color: rgb(249, 249, 249);font-size: 16px;"><span leaf="">常用例子: jstack -l pid,查看线程的堆栈信息</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">堆栈信息解读:</span></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 leaf=""><span class="code-snippet__plaintext">[root</span><span class="code-snippet__variable">@192</span><span class="code-snippet__number">-168-65-185</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">~</span><span class="code-snippet__plaintext">]# jstack </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext">l </span><span class="code-snippet__number">29440</span></span></code><code><span leaf=""><span class="code-snippet__number">2024-12-17</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">13</span><span class="code-snippet__plaintext">:</span><span class="code-snippet__number">48</span><span class="code-snippet__plaintext">:</span><span class="code-snippet__number">51</span></span></code><code><span leaf=""><span class="code-snippet__keyword">Full</span><span class="code-snippet__plaintext"> thread dump OpenJDK </span><span class="code-snippet__number">64</span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext">Bit Server VM (</span><span class="code-snippet__number">25.412</span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext">b08 mixed mode):</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"Attach Listener" #</span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f097c001000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x763a</span><span class="code-snippet__plaintext"> runnable [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"DestroyJavaVM" #</span><span class="code-snippet__number">11</span><span class="code-snippet__plaintext"> prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e004b800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7301</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">condition</span><span class="code-snippet__plaintext"> [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"pool-1-thread-1" #</span><span class="code-snippet__number">10</span><span class="code-snippet__plaintext"> prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e0166000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7316</span><span class="code-snippet__plaintext"> runnable [</span><span class="code-snippet__number">0x00007f09cc9cb000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> com.tuling.learnjuc.demo.JVMCPU$CPUTask.run(JVMCPU.java:</span><span class="code-snippet__number">16</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> locked </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d645b8</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.lang.Object)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:</span><span class="code-snippet__number">1149</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:</span><span class="code-snippet__number">624</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.Thread.run(Thread.java:</span><span class="code-snippet__number">750</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d65d00</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.util.concurrent.ThreadPoolExecutor$Worker)</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"Service Thread" #</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e0140000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7314</span><span class="code-snippet__plaintext"> runnable [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"C1 CompilerThread3" #</span><span class="code-snippet__number">8</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e0133000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7313</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">condition</span><span class="code-snippet__plaintext"> [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"C2 CompilerThread2" #</span><span class="code-snippet__number">7</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e0131000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7312</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">condition</span><span class="code-snippet__plaintext"> [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"C2 CompilerThread1" #</span><span class="code-snippet__number">6</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e012f000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7311</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">condition</span><span class="code-snippet__plaintext"> [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"C2 CompilerThread0" #</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e012c800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7310</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">condition</span><span class="code-snippet__plaintext"> [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"Signal Dispatcher" #</span><span class="code-snippet__number">4</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e011e000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x730f</span><span class="code-snippet__plaintext"> runnable [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"Finalizer" #</span><span class="code-snippet__number">3</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">8</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e00f2000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x730e</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">in</span><span class="code-snippet__plaintext"> Object.wait() [</span><span class="code-snippet__number">0x00007f09cd1d3000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: WAITING (</span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> object monitor)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.Object.wait(Native </span><span class="code-snippet__keyword">Method</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d08f00</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.lang.ref.ReferenceQueue$Lock)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:</span><span class="code-snippet__number">144</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> locked </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d08f00</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.lang.ref.ReferenceQueue$Lock)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:</span><span class="code-snippet__number">165</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:</span><span class="code-snippet__number">188</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"Reference Handler" #</span><span class="code-snippet__number">2</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">10</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e00ed000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x730d</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">in</span><span class="code-snippet__plaintext"> Object.wait() [</span><span class="code-snippet__number">0x00007f09cd2d4000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: WAITING (</span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> object monitor)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.Object.wait(Native </span><span class="code-snippet__keyword">Method</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d06b98</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.lang.ref.Reference$Lock)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.Object.wait(Object.java:</span><span class="code-snippet__number">502</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.ref.Reference.tryHandlePending(Reference.java:</span><span class="code-snippet__number">191</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> locked </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d06b98</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.lang.ref.Reference$Lock)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.ref.Reference$ReferenceHandler.run(Reference.java:</span><span class="code-snippet__number">153</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"VM Thread" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e00e3800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x730c</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#0 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e005e000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7302</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#1 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e0060000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7303</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#2 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e0062000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7304</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#3 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e0064000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7305</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#4 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e0065800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7306</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#5 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e0067800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7307</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#6 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e0069800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7308</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#7 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e006b800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7309</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#8 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e006d000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x730a</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#9 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e006f000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x730b</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"VM Periodic Task Thread" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e0142800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7315</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">condition</span><span class="code-snippet__plaintext"> </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">JNI </span><span class="code-snippet__keyword">global</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">references</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">5</span></span></code><code><span leaf=""><br></span></code></pre> </section> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uf892165a%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ua64d9cd3%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E4%BD%A0%E4%BC%9A%E5%8F%91%E7%8E%B0%E4%B8%8A%E9%9D%A2%E7%9A%84%E4%BF%A1%E6%81%AF%E5%85%B6%E5%AE%9E%E6%98%AF%E4%B8%80%E6%AE%B5%E4%B8%80%E6%AE%B5%E7%9A%84%EF%BC%8C%E6%91%98%E5%8F%96%E5%85%B6%E4%B8%AD%E7%9A%84%E4%B8%80%E6%AE%B5%E4%B8%BA%E5%A4%A7%E5%AE%B6%E8%AF%B4%E6%98%8E%3A%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">你会发现上面的信息其实是一段一段的,摘取其中的一段为大家说明:</span></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="swift"><code><span leaf=""><span class="code-snippet__string">"pool-1-thread-1"</span><span class="code-snippet__plaintext"> #</span><span class="code-snippet__number">10</span><span class="code-snippet__plaintext"> prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007f09e0166000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7316</span><span class="code-snippet__plaintext"> runnable [</span><span class="code-snippet__number">0x00007f09cc9cb000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.</span><span class="code-snippet__type">Thread</span><span class="code-snippet__plaintext">.</span><span class="code-snippet__type">State</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__type">RUNNABLE</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> at com.tuling.learnjuc.demo.</span><span class="code-snippet__type">JVMCPU</span><span class="code-snippet__variable">$CPUTask</span><span class="code-snippet__plaintext">.run(</span><span class="code-snippet__type">JVMCPU</span><span class="code-snippet__plaintext">.java:</span><span class="code-snippet__number">16</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> locked </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d645b8</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.lang.</span><span class="code-snippet__type">Object</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> at java.util.concurrent.</span><span class="code-snippet__type">ThreadPoolExecutor</span><span class="code-snippet__plaintext">.runWorker(</span><span class="code-snippet__type">ThreadPoolExecutor</span><span class="code-snippet__plaintext">.java:</span><span class="code-snippet__number">1149</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> at java.util.concurrent.</span><span class="code-snippet__type">ThreadPoolExecutor</span><span class="code-snippet__variable">$Worker</span><span class="code-snippet__plaintext">.run(</span><span class="code-snippet__type">ThreadPoolExecutor</span><span class="code-snippet__plaintext">.java:</span><span class="code-snippet__number">624</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> at java.lang.</span><span class="code-snippet__type">Thread</span><span class="code-snippet__plaintext">.run(</span><span class="code-snippet__type">Thread</span><span class="code-snippet__plaintext">.java:</span><span class="code-snippet__number">750</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__type">Locked</span><span class="code-snippet__plaintext"> ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d65d00</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.util.concurrent.</span><span class="code-snippet__type">ThreadPoolExecutor</span><span class="code-snippet__variable">$Worker</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><br></span></code></pre> </section> <ne-clipboard source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">pool-1-thread-1</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">:线程名称</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">#1</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">:当前线程ID,从main开始,jvm会根据线程创建的顺序为其线程编号</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">prio</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">:优先级的顺序,一般默认是5</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">os_prio</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">:线程对应系统的优先级</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">tid</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">:java内的线程id</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">nid</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">:操作系统级别的线程id,是一个十六进制</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">关于线程的信息:</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">NEW</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">:线程新建,还没开始运行</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">RUNNABLE</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">:正在java虚拟机中运行的线程</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">BLOCKED</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">:被阻塞,正在等待监视器锁的线程</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">WAITING</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">:无限期等待另一个线程执行特定操作的线程</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">TIMED_WAITING</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">:等待另一个线程执行操作达到指定等待时间的线程</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">TERMINATED</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">:已经退出的线程</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">我们这里关注的最多的就是</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">nid</span></span></code></p> <p><span leaf=""><br></span></p> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22cac793bb%22%2C%22name%22%3A%22h3%22%2C%22attrs%22%3A%7B%22alignment%22%3A%22justify%22%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22uc66edf16%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(30%2C%2030%2C%2030)%22%2C%22bgColor%22%3A%22rgb(212%2C%20224%2C%20250)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%222.%E4%BD%BF%E7%94%A8jstack%E8%A7%A3%E5%86%B3CPU%E5%8D%A0%E7%94%A8%E5%BE%88%E9%AB%98%E7%9A%84%E9%97%AE%E9%A2%98%E5%B9%B6%E5%AE%9A%E4%BD%8D%E5%85%B7%E4%BD%93%E8%A1%8C%E6%95%B0%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u60a188f0%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ue7737189%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E5%85%88%E6%9D%A5%E7%9C%8B%E4%B8%80%E6%AE%B5%E4%BB%A3%E7%A0%81%3A%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <h3 style="font-size: 20;line-height: 28px;margin: 16px 0 5px 0;text-align: justify;"><span style="color: rgb(30, 30, 30);background-color: rgb(212, 224, 250);"><span leaf="">2.使用jstack解决CPU占用很高的问题并定位具体行数</span></span></h3> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">先来看一段代码:</span></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 leaf=""><span class="code-snippet__keyword">package</span><span class="code-snippet__plaintext"> com.tuling.learnjuc.demo;</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__keyword">import</span><span class="code-snippet__plaintext"> java.util.concurrent.ExecutorService;</span></span></code><code><span leaf=""><span class="code-snippet__keyword">import</span><span class="code-snippet__plaintext"> java.util.concurrent.Executors;</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__keyword">public</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">class</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">JVMCPU</span><span class="code-snippet__plaintext"> {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">static</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__type">ExecutorService</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__variable">service</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">=</span><span class="code-snippet__plaintext"> Executors.newFixedThreadPool(</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext">);</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">static</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__type">Object</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__variable">lock</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">=</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">new</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">Object</span><span class="code-snippet__plaintext">();</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">public</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">static</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">class</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">CPUTask</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">implements</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">Runnable</span><span class="code-snippet__plaintext">{</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__meta">@Override</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">public</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">void</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">run</span><span class="code-snippet__params">()</span><span class="code-snippet__plaintext"> {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">synchronized</span><span class="code-snippet__plaintext"> (lock){</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__type">long</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__variable">sum</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">=</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">0L</span><span class="code-snippet__plaintext">;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">while</span><span class="code-snippet__plaintext">(</span><span class="code-snippet__literal">true</span><span class="code-snippet__plaintext">){</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> sum +=</span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext">;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> }</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> }</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> }</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> }</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">public</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">static</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">void</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">main</span><span class="code-snippet__params">(String[] args)</span><span class="code-snippet__plaintext"> {</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__type">CPUTask</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__variable">cpuTask</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">=</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">new</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">CPUTask</span><span class="code-snippet__plaintext">();</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> service.execute(cpuTask);</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> }</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">}</span></span></code></pre> </section> <ne-clipboard source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">将这段代码上传到linux服务器上编译</span></span></p> <blockquote> <p><span leaf="">注意:如果提示javac: 未找到命令... ,执行yum install java-1.8.0-openjdk-devel</span></p> </blockquote> <section style="text-align: center;" nodeleaf=""> <img src="/upload/6308f670d43b04544082eea73df6eb9d.png" class="rich_pages wxw-img" data-ratio="0.15648148148148147" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100000552"> </section> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ua6fa8133%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22uc6d06727%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E4%BD%BF%E7%94%A8%22%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ub2fca604%22%2C%22name%22%3A%22code%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ub57edd22%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A14%7D%2C%22data%22%3A%22nohup%20java%20com.tuling.learnjuc.demo.JVMCPU%20%26%22%7D%5D%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u4b0806c9%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E8%BF%90%E8%A1%8C%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">使用</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">nohup java com.tuling.learnjuc.demo.JVMCPU &</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">运行</span></span></p> <section style="text-align: center;" nodeleaf=""> <img src="/upload/a12b669534709ff59d3119cb89b5d9ba.png" class="rich_pages wxw-img" data-ratio="0.09259259259259259" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100000553"> </section> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u3956adf8%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22uc0f107ee%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E4%BD%BF%E7%94%A8%22%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u2e993f78%22%2C%22name%22%3A%22code%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u9aa59a80%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A14%7D%2C%22data%22%3A%22top%22%7D%5D%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u7a5b5797%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E5%91%BD%E4%BB%A4%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0cpu%E8%A2%AB%E6%89%93%E6%BB%A1%E4%BA%86%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">使用</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">top</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">命令可以看到cpu被打满了</span></span></p> <section style="text-align: center;" nodeleaf=""> <img src="/upload/705102066230ac8b4e6da507a87ba670.png" class="rich_pages wxw-img" data-ratio="0.2518518518518518" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100000554"> </section> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u02192818%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u6217cd25%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E7%9F%A5%E9%81%93%E4%BA%86%E8%BF%9B%E7%A8%8B%E7%9A%84PID%EF%BC%8C%E5%A6%82%E4%BD%95%E6%89%BE%E5%88%B0%E8%BF%9B%E7%A8%8B%E4%B8%8B%E6%98%AF%E5%93%AA%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%91%A2%3F%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8%E5%91%BD%E4%BB%A4%22%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u6e9b242b%22%2C%22name%22%3A%22code%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u4d9d0f9e%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A14%7D%2C%22data%22%3A%22top%20-Hp%2032208%22%7D%5D%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u733b01bb%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%EF%BC%8C%E5%A6%82%E4%B8%8B%E6%89%80%E7%A4%BA%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">知道了进程的PID,如何找到进程下是哪个线程呢?可以使用命令</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">top -Hp 32208</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">,如下所示</span></span></p> <section style="text-align: center;" nodeleaf=""> <img src="/upload/aad572d136738c1c52b22e0712e02574.png" class="rich_pages wxw-img" data-ratio="0.41759259259259257" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100000555"> </section> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ua9754ccd%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u756781cf%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E5%A6%82%E6%9E%9C%E8%83%BD%E8%8E%B7%E5%8F%96%E5%88%B0%E7%BA%BF%E7%A8%8B%E5%90%8D%EF%BC%8C%E4%B8%8B%E9%9D%A2%E8%BF%99%E6%AD%A5%E5%8F%AF%E4%BB%A5%E5%BF%BD%E7%95%A5%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">如果能获取到线程名,下面这步可以忽略,不需要根据线程id找线程</span></span></p> <ne-clipboard source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <blockquote> <p><span leaf="">从上面的图可以看到,cpu占用最多的线程是32230这个线程id,接下来就是使用jstack命令来查看程序的所有堆栈信息,但是,这里需要有一个注意的点,32230这个是一个十进制的,使用jstack看到的nid是十六进制,所以我们需要转换,可以使用printf "%x\n"这个命令</span></p> </blockquote> <section style="text-align: center;" nodeleaf=""> <img src="/upload/82d59d77bd9a585d0d33e504c255ba3f.png" class="rich_pages wxw-img" data-ratio="0.09235352532274081" data-s="300,640" data-type="png" data-w="1007" type="block" data-imgfileid="100000556"> </section> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uc00ab2f9%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u1c78913f%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E6%8E%A5%E4%B8%8B%E6%9D%A5%E4%BD%BF%E7%94%A8%22%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u30ca27f7%22%2C%22name%22%3A%22code%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u57e962c7%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A14%7D%2C%22data%22%3A%22jstack%20-l%2032208%22%7D%5D%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u057484d9%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E6%89%93%E5%8D%B0%E5%A0%86%E6%A0%88%E4%BF%A1%E6%81%AF%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">接下来使用</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">jstack -l 32208</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">打印堆栈信息</span></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 leaf=""><span class="code-snippet__plaintext">[root</span><span class="code-snippet__variable">@192</span><span class="code-snippet__number">-168-65-185</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">~</span><span class="code-snippet__plaintext">]# jstack </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext">l </span><span class="code-snippet__number">32208</span></span></code><code><span leaf=""><span class="code-snippet__number">2024-12-17</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">14</span><span class="code-snippet__plaintext">:</span><span class="code-snippet__number">04</span><span class="code-snippet__plaintext">:</span><span class="code-snippet__number">09</span></span></code><code><span leaf=""><span class="code-snippet__keyword">Full</span><span class="code-snippet__plaintext"> thread dump OpenJDK </span><span class="code-snippet__number">64</span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext">Bit Server VM (</span><span class="code-snippet__number">25.412</span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext">b08 mixed mode):</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"Attach Listener" #</span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb498001000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x4e5</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">condition</span><span class="code-snippet__plaintext"> [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"DestroyJavaVM" #</span><span class="code-snippet__number">11</span><span class="code-snippet__plaintext"> prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc04b800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7dd1</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">condition</span><span class="code-snippet__plaintext"> [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"pool-1-thread-1" #</span><span class="code-snippet__number">10</span><span class="code-snippet__plaintext"> prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc16e000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7de6</span><span class="code-snippet__plaintext"> runnable [</span><span class="code-snippet__number">0x00007fb4e87fe000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> com.tuling.learnjuc.demo.JVMCPU$CPUTask.run(JVMCPU.java:</span><span class="code-snippet__number">16</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> locked </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d645b8</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.lang.Object)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:</span><span class="code-snippet__number">1149</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:</span><span class="code-snippet__number">624</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.Thread.run(Thread.java:</span><span class="code-snippet__number">750</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d65d00</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.util.concurrent.ThreadPoolExecutor$Worker)</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"Service Thread" #</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc140000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7de4</span><span class="code-snippet__plaintext"> runnable [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"C1 CompilerThread3" #</span><span class="code-snippet__number">8</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc133000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7de3</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">condition</span><span class="code-snippet__plaintext"> [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"C2 CompilerThread2" #</span><span class="code-snippet__number">7</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc131000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7de2</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">condition</span><span class="code-snippet__plaintext"> [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"C2 CompilerThread1" #</span><span class="code-snippet__number">6</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc12f000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7de1</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">condition</span><span class="code-snippet__plaintext"> [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"C2 CompilerThread0" #</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc12c800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7de0</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">condition</span><span class="code-snippet__plaintext"> [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"Signal Dispatcher" #</span><span class="code-snippet__number">4</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">9</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc11e000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7ddf</span><span class="code-snippet__plaintext"> runnable [</span><span class="code-snippet__number">0x0000000000000000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: RUNNABLE</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"Finalizer" #</span><span class="code-snippet__number">3</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">8</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc0f2000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7dde</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">in</span><span class="code-snippet__plaintext"> Object.wait() [</span><span class="code-snippet__number">0x00007fb4e92d4000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: WAITING (</span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> object monitor)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.Object.wait(Native </span><span class="code-snippet__keyword">Method</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d08f00</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.lang.ref.ReferenceQueue$Lock)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:</span><span class="code-snippet__number">144</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> locked </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d08f00</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.lang.ref.ReferenceQueue$Lock)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:</span><span class="code-snippet__number">165</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:</span><span class="code-snippet__number">188</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"Reference Handler" #</span><span class="code-snippet__number">2</span><span class="code-snippet__plaintext"> daemon prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">10</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc0ed000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7ddd</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">in</span><span class="code-snippet__plaintext"> Object.wait() [</span><span class="code-snippet__number">0x00007fb4e93d5000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.Thread.State: WAITING (</span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> object monitor)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.Object.wait(Native </span><span class="code-snippet__keyword">Method</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d06b98</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.lang.ref.Reference$Lock)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.Object.wait(Object.java:</span><span class="code-snippet__number">502</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.ref.Reference.tryHandlePending(Reference.java:</span><span class="code-snippet__number">191</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> locked </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d06b98</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.lang.ref.Reference$Lock)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">at</span><span class="code-snippet__plaintext"> java.lang.ref.Reference$ReferenceHandler.run(Reference.java:</span><span class="code-snippet__number">153</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> Locked ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">None</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"VM Thread" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc0e3800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7ddc</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#0 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc05e000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7dd2</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#1 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc060000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7dd3</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#2 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc062000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7dd4</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#3 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc064000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7dd5</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#4 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc065800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7dd6</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#5 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc067800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7dd7</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#6 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc069800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7dd8</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#7 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc06b800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7dd9</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#8 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc06d000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7dda</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"GC task thread#9 (ParallelGC)" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc06f000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7ddb</span><span class="code-snippet__plaintext"> runnable </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">"VM Periodic Task Thread" os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc142800</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7de5</span><span class="code-snippet__plaintext"> waiting </span><span class="code-snippet__keyword">on</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">condition</span><span class="code-snippet__plaintext"> </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">JNI </span><span class="code-snippet__keyword">global</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">references</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">5</span></span></code></pre> </section> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u945352f9%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ua36776a6%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E4%BB%8E%E4%B8%8A%E9%9D%A2%E7%9A%84%E4%BF%A1%E6%81%AF%E4%B8%AD%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E8%BD%AC%E6%8D%A2%E7%9A%84%E7%BB%93%E6%9E%9C%E5%92%8Cnid%E6%98%AF%E4%B8%80%E8%87%B4%E7%9A%84%EF%BC%8C%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u785f5c7c%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22uf33a65a8%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E4%BB%8E%E4%B8%8B%E9%9D%A2%E7%9A%84%E4%BF%A1%E6%81%AF%E4%B8%AD%E5%B0%B1%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E9%97%AE%E9%A2%98%E5%85%B6%E5%AE%9E%E6%98%AF%E5%87%BA%E7%8E%B0%E5%9C%A8%22%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ue3e43fb0%22%2C%22name%22%3A%22code%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u5a80d1f9%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A14%7D%2C%22data%22%3A%22JVMCPU.java%22%7D%5D%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u890b199a%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E7%9A%8416%E8%A1%8C%E5%B7%A6%E5%8F%B3%EF%BC%8C%E8%BF%99%E9%87%8C%E7%BB%99%E5%87%BA%E7%9A%84%E6%98%AF16%E8%A1%8C%EF%BC%8C%E4%BD%86%E6%98%AF%E5%AE%9E%E9%99%85%E6%83%85%E5%86%B5%E6%98%AF16%E8%A1%8C%E7%9A%84%E9%99%84%E8%BF%91%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">从上面的信息中,可以看到转换的结果和nid是一致的,</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">从下面的信息中就可以看到问题其实是出现在</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">JVMCPU.java</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">的16行左右,这里给出的是16行,但是实际情况是16行的附近</span></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="swift"><code><span leaf=""><span class="code-snippet__string">"pool-1-thread-1"</span><span class="code-snippet__plaintext"> #</span><span class="code-snippet__number">10</span><span class="code-snippet__plaintext"> prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext"> os_prio</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> tid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x00007fb4fc16e000</span><span class="code-snippet__plaintext"> nid</span><span class="code-snippet__operator">=</span><span class="code-snippet__number">0x7de6</span><span class="code-snippet__plaintext"> runnable [</span><span class="code-snippet__number">0x00007fb4e87fe000</span><span class="code-snippet__plaintext">]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> java.lang.</span><span class="code-snippet__type">Thread</span><span class="code-snippet__plaintext">.</span><span class="code-snippet__type">State</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__type">RUNNABLE</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> at com.tuling.learnjuc.demo.</span><span class="code-snippet__type">JVMCPU</span><span class="code-snippet__variable">$CPUTask</span><span class="code-snippet__plaintext">.run(</span><span class="code-snippet__type">JVMCPU</span><span class="code-snippet__plaintext">.java:</span><span class="code-snippet__number">16</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> locked </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d645b8</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.lang.</span><span class="code-snippet__type">Object</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> at java.util.concurrent.</span><span class="code-snippet__type">ThreadPoolExecutor</span><span class="code-snippet__plaintext">.runWorker(</span><span class="code-snippet__type">ThreadPoolExecutor</span><span class="code-snippet__plaintext">.java:</span><span class="code-snippet__number">1149</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> at java.util.concurrent.</span><span class="code-snippet__type">ThreadPoolExecutor</span><span class="code-snippet__variable">$Worker</span><span class="code-snippet__plaintext">.run(</span><span class="code-snippet__type">ThreadPoolExecutor</span><span class="code-snippet__plaintext">.java:</span><span class="code-snippet__number">624</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> at java.lang.</span><span class="code-snippet__type">Thread</span><span class="code-snippet__plaintext">.run(</span><span class="code-snippet__type">Thread</span><span class="code-snippet__plaintext">.java:</span><span class="code-snippet__number">750</span><span class="code-snippet__plaintext">)</span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__type">Locked</span><span class="code-snippet__plaintext"> ownable synchronizers:</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator"><</span><span class="code-snippet__number">0x0000000757d65d00</span><span class="code-snippet__operator">></span><span class="code-snippet__plaintext"> (a java.util.concurrent.</span><span class="code-snippet__type">ThreadPoolExecutor</span><span class="code-snippet__variable">$Worker</span><span class="code-snippet__plaintext">)</span></span></code></pre> </section> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u735539b8%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u1cf8c957%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E7%BB%93%E5%90%88%E4%BB%A3%E7%A0%81%E6%9D%A5%E7%9C%8B%E4%B8%80%E4%B8%8B%E5%B0%B1%E5%BE%88%E5%AE%B9%E6%98%93%E9%97%AE%E9%A2%98%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">结合代码来看一下就很容易问题</span></span></p> <section style="text-align: center;" nodeleaf=""> <img src="/upload/bb317db1e974d25ffad82477018eef05.png" class="rich_pages wxw-img" data-ratio="0.5370370370370371" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100000557"> </section> <ne-clipboard source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <h2 style="font-size: 24px;line-height: 32px;margin: 21px 0 5px 0;text-align: justify;"><span leaf="">使用arthas解决CPU占用很高的问题,定位具体代码行</span></h2> <blockquote> <p><span leaf="">官方文档:https://arthas.aliyun.com/</span></p> </blockquote> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">使用arthas解决CPU 100%问题,在方法论上要用到两个命令,</span></span></p> <ul style="margin: 0;padding-left: 23px;" class="list-paddingleft-1"> <li><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">dashboard 命令查看TOP N线程,</span></span></li> <li><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">thread 命令查看堆栈信息</span></span></li> </ul> <section style="text-align: center;" nodeleaf=""> <img src="/upload/3d18c01c27599aee3b71ff26de99cd51.png" class="rich_pages wxw-img" data-ratio="0.1875" data-s="300,640" data-type="png" data-w="960" type="block" data-imgfileid="100000558"> </section> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ued510460%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ufc299fb5%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E5%85%88%E6%9D%A5%E8%BF%90%E8%A1%8C%22%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uea1befb8%22%2C%22name%22%3A%22code%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22uf9070dcd%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A14%7D%2C%22data%22%3A%22arthas%22%7D%5D%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">先来运行</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">arthas</span></span></code></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="javascript"><code><span leaf=""><span class="code-snippet__plaintext">curl -O </span><span class="code-snippet__attr">https</span><span class="code-snippet__plaintext">:</span><span class="code-snippet__comment">//arthas.aliyun.com/arthas-boot.jar</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">java -jar arthas-boot.jar</span></span></code></pre> </section> <section style="text-align: center;" nodeleaf=""> <img src="/upload/e36a50ada6d50c481516880aa0f53d49.png" class="rich_pages wxw-img" data-ratio="0.15648148148148147" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100000559"> </section> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u9ce49312%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u7fe07ffd%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E8%BE%93%E5%85%A51%E6%98%BE%E7%A4%BA%E5%A6%82%E4%B8%8B%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">输入1显示如下</span></span></p> <section style="text-align: center;" nodeleaf=""> <img src="/upload/88c44b712e6225727d6e40767843f9d1.png" class="rich_pages wxw-img" data-ratio="0.42962962962962964" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100000560"> </section> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uf850238f%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u2903f06b%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E8%BE%93%E5%85%A5%22%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u1b8a3032%22%2C%22name%22%3A%22code%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u185ac0da%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A14%7D%2C%22data%22%3A%22dashboard%22%7D%5D%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ub9d55c98%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E5%91%BD%E4%BB%A4%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E6%98%AF%E5%93%AA%E4%B8%AA%E7%BA%BF%E7%A8%8B%E5%8D%A0%E7%94%A8cpu%E6%9C%80%E9%AB%98%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">输入</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">dashboard</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">命令可以看到是哪个线程占用cpu最高</span></span></p> <section style="text-align: center;" nodeleaf=""> <img src="/upload/677ff822ea056b5a88fdd152c7cf7d0b.png" class="rich_pages wxw-img" data-ratio="0.1925925925925926" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100000561"> </section> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u0cef716e%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ua5a08470%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E6%8E%A5%E4%B8%8B%E6%9D%A5%E8%BE%93%E5%85%A5%22%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u12324012%22%2C%22name%22%3A%22code%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u0ae40b08%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A14%7D%2C%22data%22%3A%22thread%20-n%201%22%7D%5D%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u5a90496d%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%EF%BC%8C%E8%A1%A8%E7%A4%BA%E6%9C%80%E5%BF%99%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%B9%B6%E6%89%93%E5%8D%B0%E4%BF%A1%E6%81%AF%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">接下来输入</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">thread -n 1</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">,表示最忙的线程并打印信息</span></span></p> <section style="text-align: center;" nodeleaf=""> <img src="/upload/70b151164fbc3d1a7ac6405d6d11e935.png" class="rich_pages wxw-img" data-ratio="0.1685185185185185" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100000562"> </section> <ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uc738d1c7%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22uc5f4a49b%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E4%BB%8E%E4%B8%8A%E9%9D%A2%E7%9A%84%E5%9B%BE%E4%B8%AD%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0arthas%E5%92%8Cjstack%E5%B1%95%E7%A4%BA%E7%9A%84%E4%BF%A1%E6%81%AF%E5%B7%AE%E4%B8%8D%E5%A4%9A%EF%BC%8C%E9%83%BD%E5%AE%9A%E4%BD%8D%E5%88%B0%E4%BA%86%22%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u97799645%22%2C%22name%22%3A%22code%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u2ada2ae5%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A14%7D%2C%22data%22%3A%22JVMCPU.java%22%7D%5D%7D%2C%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ud5a90fda%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(36%2C%2041%2C%2046)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E7%9A%8416%E8%A1%8C%E7%A8%8B%E5%BA%8F%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fkdotyfqesdqxhh8o"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">从上面的图中可以看到arthas和jstack展示的信息差不多,都定位到了</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(36, 41, 46);font-size: 14px;"><span leaf="">JVMCPU.java</span></span></code><span style="color: rgb(36, 41, 46);font-size: 16px;"><span leaf="">的16行程序</span></span></p>
作者:微信小助手
<article> <h2 yne-bulb-block="heading" yne-bulb-level="2" style="white-space:pre-wrap;line-height:1.75;font-size:14px;text-align:left;"><span style="font-weight: bold;font-size: 20px;"><span leaf="">1. 什么是深度分页</span></span></h2> <p><span style="color: rgb(243, 50, 50);"><span leaf="">深度分页是指在处理大数据集查询时,用户尝试访问多页数据中较后面的页面时遇到的问题</span></span><span leaf="">。当尝试访问排序后的数据列表的第1000页或更后面的页面时,数据库需要先跳过前面数十万条记录,这一过程通常涉及大量的数据扫描和排序,极大地增加了数据库的查询负载,从而成为性能瓶颈。</span></p> <p><span leaf="">ES分页查询流程大致如下:</span></p> <ol style="margin:0px;margin-left: 14px;" class="list-paddingleft-1"> <li> <section> <span leaf="">数据存储在各个分片中,协调节点将查询请求转发给各个节点,当各个节点执行搜索后,将排序后的前N条数据返回给协调节点。</span> </section></li> <li> <section> <span leaf="">协调节点汇总各个分片返回的数据,再次排序,最终返回前N条数据给客户端。</span> </section></li> <li> <section> <span leaf="">这个流程会导致一个深度分页的问题,也就是翻页越多,性能越差,甚至导致ES出现OOM。</span> </section></li> </ol> <p><span style="color: rgb(243, 50, 50);"><span leaf="">在分布式系统中,对结果排序的成本随分页的深度成指数上升。</span></span></p> <p><span leaf="">从10万名高考生中查询成绩为的10001-10100位的100名考生的信息。</span></p> <section nodeleaf=""> <img src="/upload/c2120a9e540183a1b8e6a807c3188baa.png" class="rich_pages wxw-img" data-ratio="0.5971143174250833" data-type="png" data-w="901" height="384" style="width: 629px;height: 384px;" width="629" data-imgfileid="100000297"> </section> <p><span leaf="">从上面案例中不难看出,每次有序的查询都会在每个分片中执行单独的查询,然后进行数据的二次排序,而这个二次排序的过程是发生在heap中的,也就是说当你单次查询的数量越大,那么堆内存中汇总的数据也就越多,对内存的压力也就越大。这里的单次查询的数据量取决于你查询的是第几条数据而不是查询了几条数据,比如你希望查询的是第10001-10100这一百条数据,但是ES必须将前10100全部取出进行二次查询。因此,</span><span style="color: rgb(243, 50, 50);"><span leaf="">如果查询的数据排序越靠后,就越容易导致OOM(Out Of Memory)情况的发生,频繁的深分页查询会导致频繁的FullGC。</span></span></p> <p><span style="color: rgb(77, 77, 77);background-color: rgb(255, 255, 255);font-size: 14px;font-family: Arial;"><span leaf="">ES为了避免用户在不了解其内部原理的情况下而做出错误的操作,设置了一个阈值,即</span></span><span style="font-size: 14px;"><span leaf="">max_result_window</span></span><span style="color: rgb(77, 77, 77);background-color: rgb(255, 255, 255);font-size: 14px;font-family: Arial;"><span leaf="">,其默认值为</span></span><span style="font-size: 14px;"><span leaf="">10000</span></span><span style="color: rgb(77, 77, 77);background-color: rgb(255, 255, 255);font-size: 14px;font-family: Arial;"><span leaf="">,</span></span><span style="color: rgb(243, 50, 50);background-color: rgb(255, 255, 255);font-size: 14px;font-family: Arial;"><span leaf="">其作用是为了保护堆内存不被错误操作导致溢出。</span></span></p> <p><span style="font-weight: bold;"></span></p> <h2 yne-bulb-block="heading" yne-bulb-level="2" style="white-space:pre-wrap;line-height:1.75;font-size:14px;text-align:left;"><span style="font-weight: bold;font-size: 20px;"><span leaf="">2. 深度分页不推荐使用from+size</span></span></h2> <p><span leaf="">在Elasticsearch中,分页查询的实现主要通过两个参数from和size来实现。from参数指定了从结果集中的第几条数据开始返回,而size参数指定了返回数据的数量。正常情况下分页代码如实下面这样的:</span></p> </article> <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="css"><code><span leaf=""><span class="code-snippet__plaintext"># 查询第一页</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext">条数据</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">GET /employee/_search</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">{</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> "query": {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> "match_all": {}</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> },</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> "</span><span class="code-snippet__selector-tag">from</span><span class="code-snippet__plaintext">": </span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"size"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext"> </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">}</span></span></code></pre> </section> <article> <p><span leaf="">输出结果如下图:</span></p> <section nodeleaf=""> <img src="/upload/43a8784098ea2c6fad05cf20d685d27d.png" class="rich_pages wxw-img" data-ratio="1.4823529411764707" data-type="png" data-w="340" height="504" style="width: 340px;height: 504px;" width="340" data-imgfileid="100000299"> </section> <p><span leaf="">但是如果我们查询的数据页数特别大,当from + size大于10000的时候,就会出现问题,如下图报错信息所示:</span></p> <section nodeleaf=""> <img src="/upload/a3c241dc22dd8dfbad2fa510b0684b15.png" class="rich_pages wxw-img" data-ratio="0.28055555555555556" data-type="png" data-w="1080" height="503" style="width: 1794px;height: 503px;" width="1794" data-imgfileid="100000300"> </section> <p><span leaf="">分析可知,查询结果的窗口大小超过了最大窗口的限制,而index. max_result_window默认值为10000。</span></p> <p><span style="color: rgb(243, 50, 50);"><span leaf="">Elasticsearch会限制最大分页数,避免因大数据量的召回导致系统性能低下。</span></span><span leaf="">Elasticsearch的max_result_window默认值是10000,意味着每页有10条数据,会最大翻页至1000页。主流搜索引擎实际都翻不了那么多页。</span></p> <p><span leaf="">对此,有两个可行的解决方案,如下所示:</span></p> <ul style="margin:0px;margin-left: 14px;" class="list-paddingleft-1"> <li> <section> <span leaf="">方案一:对于大型数据集,我们可采用scroll API来召回数据。这个策略我们将在后续的内容中进行详细分析。</span> </section></li> <li> <section> <span leaf="">方案二:调大index.max_result_window默认值</span> </section></li> </ul> </article> <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="bash"><code><span leaf=""><span class="code-snippet__plaintext">PUT /employee/_settings</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">{</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"index.max_result_window"</span><span class="code-snippet__plaintext">: 20000</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">}</span></span></code></pre> </section> <article> <p><span style="color: rgb(243, 50, 50);"><span leaf="">官方建议避免使用from+size来过度分页或一次请求太多结果。</span></span></p> <p><span leaf="">不推荐使用from+size来深度分页的核心原因如下:</span></p> <ul style="margin:0px;margin-left: 14px;" class="list-paddingleft-1"> <li> <section> <span leaf="">搜索请求通常会跨多个分片,每个分片必须将其请求的命中内容以及先前页面的命中内容加载到内存中。</span> </section></li> <li> <section> <span leaf="">对于分页较多的页面或大量结果,这样操作会显著增加内存和CPU使用率,导致性能下降,甚至导致节点故障。</span> </section></li> </ul> <h3 yne-bulb-block="heading" yne-bulb-level="3" style="white-space:pre-wrap;line-height:1.75;font-size:14px;text-align:left;"><span style="font-weight: bold;font-size: inherit;"><span leaf="">from+size查询的优缺点及适用场景</span></span></h3> <p><span leaf="">from+size分页查询的优缺点如下:</span></p> <ul style="margin:0px;margin-left: 14px;" class="list-paddingleft-1"> <li> <section> <span leaf="">from+size查询优点:支持随机翻页。</span> </section></li> <li> <section> <span leaf="">from+size查询缺点:</span> </section></li> </ul> <p><span leaf="">from+size查询适用场景如下:</span></p> <ul style="margin:0px;margin-left: 14px;" class="list-paddingleft-1"> <li> <section> <span leaf="">非常适合小型数据集或者从大数据集中返回Top N(N≤10000)结果集的业务场景。</span> </section></li> <li> <section> <span leaf="">主流PC搜索引擎中支持随机跳转分页的业务场景,如下图所示:</span> </section></li> </ul> <section nodeleaf=""> <img src="/upload/35afb1f9a0f31cf69522060219414d2b.png" class="rich_pages wxw-img" data-ratio="0.5305389221556887" data-type="png" data-w="835" height="443" style="width: 835px;height: 443px;" width="835" data-imgfileid="100000302"> </section> <p><span style="color: rgb(243, 50, 50);background-color: rgb(255, 255, 255);font-size: 14px;font-family: Arial;"></span></p> <h2 yne-bulb-block="heading" yne-bulb-level="2" style="white-space:pre-wrap;line-height:1.75;font-size:14px;text-align:left;"><span style="font-weight: bold;font-size: 20px;"><span leaf="">3</span></span><span style="font-weight: bold;font-size: 20px;"><span leaf="">.</span></span><span style="font-weight: bold;font-size: 20px;"><span leaf="">深度分页问题的常见解决方案</span></span></h2> <h3 yne-bulb-block="heading" yne-bulb-level="3" style="white-space:pre-wrap;line-height:1.75;font-size:14px;text-align:left;"><span style="font-weight: bold;font-size: inherit;"><span leaf="">尝试避免使用深度分页</span></span></h3> <p><span style="color: rgb(243, 50, 50);"><span leaf="">解决深度分页问题最好的办法就是避免使用深度分页。</span></span><span style="color: rgb(77, 77, 77);background-color: rgb(255, 255, 255);font-family: Arial;"><span leaf="">谷歌、</span></span><span style="background-color: rgb(255, 255, 255);font-family: Arial;"><span leaf="">百度</span></span><span style="color: rgb(77, 77, 77);background-color: rgb(255, 255, 255);font-family: Arial;"><span leaf="">目前作为全球和国内做大的搜索引擎不约而同的在分页条中</span></span><span style="color: rgb(243, 50, 50);background-color: rgb(255, 255, 255);font-family: Arial;"><span leaf="">删除了“</span></span><span style="color: rgb(243, 50, 50);"><span leaf="">跳页</span></span><span style="color: rgb(243, 50, 50);background-color: rgb(255, 255, 255);font-family: Arial;"><span leaf="">”功能</span></span><span style="color: rgb(77, 77, 77);background-color: rgb(255, 255, 255);font-family: Arial;"><span leaf="">,其目的就是为了避免用户使用深度分页检索。</span></span></p> <section nodeleaf=""> <img src="/upload/35afb1f9a0f31cf69522060219414d2b.png" class="rich_pages wxw-img" data-ratio="0.5305389221556887" data-type="png" data-w="835" height="337" style="width: 606px;height: 337px;" width="606" data-imgfileid="100000303"> </section> <p><span leaf="">在百度中搜索“Elasticsearch”,在搜索结果中翻到第20页,就无法再往下翻页了,提示信息如下图:</span></p> <section nodeleaf=""> <img src="/upload/f467a6ed1710cb89b0d3cefa94944426.png" class="rich_pages wxw-img" data-ratio="0.6416666666666667" data-type="png" data-w="1080" height="835" style="width: 1302px;height: 835px;" width="1302" data-imgfileid="100000305"> </section> <p><span style="text-decoration: underline;color: rgb(3, 102, 214);"><span leaf="">淘宝</span></span><span leaf="">虽然没有删除“跳页”功能,但不管我们搜索什么内容,只要商品结果足够多,返回的商品列表都是仅展示前100页的数据,其本质和ES中的max_result_window作用是一样的,都是限制你去搜索更深页数的数据。</span></p> <section nodeleaf=""> <img src="/upload/25371c2068d4ba8a79fbad862105497a.png" class="rich_pages wxw-img" data-ratio="0.3522727272727273" data-type="png" data-w="1056" height="266" style="width: 752px;height: 266px;" width="752" data-imgfileid="100000304"> </section> <p><span leaf="">手机端APP就更不用说了,直接是下拉加载更多,连分页条都没有,相当于你只能点击“下一页”。</span></p> <h3 yne-bulb-block="heading" yne-bulb-level="3" style="white-space:pre-wrap;line-height:1.75;font-size:14px;text-align:left;"><span style="font-weight: bold;font-size: inherit;"><span leaf="">Scroll Search</span></span><span style="font-weight: bold;font-size: inherit;"><span leaf="">滚动查询</span></span></h3> <p><span style="color: rgb(243, 50, 50);"><span leaf="">scroll API可从单个搜索请求中检索大量结果(甚至所有结果)</span></span><span leaf="">,这种方式与传统数据库中的游标(cursor)类似。</span><span style="color: rgb(243, 50, 50);"><span leaf="">scroll滚动遍历查询是非实时的</span></span><span leaf="">,数据量大的时候,响应时间可能会比较长。</span></p> <blockquote> <p><span leaf="">官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/8.14/paginate-search-results.html#scroll-search-results</span></p> </blockquote> <p><span style="color: rgb(243, 50, 50);"><span leaf="">ES7之后,官方已经不再建议使用scroll API进行深度分页。</span></span><span leaf="">如果要分页检索超过 Top 10,000+ 结果时,推荐使用:search_after。</span></p> <section nodeleaf=""> <img src="/upload/f8121780f02a53f94014c7bb71e5bba0.png" class="rich_pages wxw-img" data-ratio="0.12488350419384903" data-type="png" data-w="1073" height="134" style="width: 1073px;height: 134px;" width="1073" data-imgfileid="100000301"> </section> <p><span style="font-weight: bold;"><span leaf="">适合场景</span></span></p> <p><span leaf="">单个滚动搜索请求中检索大量结果,即非“C端业务”场景</span></p> <h4 yne-bulb-block="heading" yne-bulb-level="4" style="white-space:pre-wrap;line-height:1.75;font-size:14px;text-align:left;"><span style="font-weight: bold;"><span leaf="">实现步骤</span></span></h4> <p><span leaf="">scroll查询的核心执行步骤如下。</span></p> <p><span style="font-weight: bold;"><span leaf="">1) 第一次进行scroll查询,指定检索语句的同时设置scroll上下文保留时间。</span></span></p> <p><span leaf="">scroll请求返回的结果反映了发出初始搜索请求时索引的状态,就像在那一个时刻做了快照,随后对文档的更改(写入、更新或删除)只会影响以后的搜索请求。</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="swift"><code><span leaf=""><span class="code-snippet__plaintext"># 使用kibana提供的航班测试数据集</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">#查询命令中新增scroll</span><span class="code-snippet__operator">=</span><span class="code-snippet__plaintext">5m,说明采用游标查询,保持游标查询窗口</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext">分钟,也就是本次快照的结果缓存起来的有效时间是</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext">分钟</span><span class="code-snippet__operator">。</span></span></code><code><span leaf=""><span class="code-snippet__type">GET</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__regexp">/kibana_sample_data_flights/</span><span class="code-snippet__plaintext">_search</span><span class="code-snippet__operator">?</span><span class="code-snippet__plaintext">scroll</span><span class="code-snippet__operator">=</span><span class="code-snippet__plaintext">5m </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">{</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"query"</span><span class="code-snippet__plaintext">: {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"term"</span><span class="code-snippet__plaintext">: {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"OriginWeather"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"Sunny"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> }</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> },</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"size"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">100</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">}</span></span></code></pre> </section> <p><span leaf=""><br></span></p> </article> <article data-content="[{"type":"block","id":"5759-1652538006122","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"BfrC-1688026638080","leaves":[{"text":"返回结果:","marks":[]}]}],"state":{}},{"type":"block","id":"Zkdh-1723984881982","name":"image","data":{"version":1,"url":"https://note.youdao.com/yws/res/f/WEBRESOURCEd42f7ebf11466088efe7cce6fa0b5e4f","width":949,"height":443,"fromIdentity":""},"nodes":[],"state":{"renderSource":"https://note.youdao.com/yws/res/f/WEBRESOURCEd42f7ebf11466088efe7cce6fa0b5e4f","initialSize":{"width":949,"height":443},"loading":false}},{"type":"block","id":"8381-1652538006122","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"PIsS-1688026638080","leaves":[{"text":"2) 向后翻页,继续获取数据,直到没有要返回的结果为止","marks":[{"type":"bold"}]}]}],"state":{}}]"> <p><span leaf="">返回结果:</span></p> <section nodeleaf=""> <img src="/upload/6cc1f04accb3292c1593e8d08414561b.png" class="rich_pages wxw-img" data-ratio="0.46680716543730244" data-type="png" data-w="949" height="443" style="width: 949px;height: 443px;" width="949" data-imgfileid="100000306"> </section> <p><span style="font-weight: bold;"><span leaf="">2) 向后翻页,继续获取数据,直到没有要返回的结果为止</span></span></p> </article> <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="swift"><code><span leaf=""><span class="code-snippet__plaintext"># scroll_id 的值就是上一个请求中返回的 _scroll_id 的值</span></span></code><code><span leaf=""><span class="code-snippet__type">GET</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__regexp">/_search/</span><span class="code-snippet__plaintext">scroll</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">{</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"scroll"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"5m"</span><span class="code-snippet__plaintext">, </span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"scroll_id"</span><span class="code-snippet__plaintext"> : </span><span class="code-snippet__string">"FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFnQ5MUF6M3dYUkhPQW81czY3RXBDckEAAAAAABkMUBZPOVotS1A1MlI1dU43QXFsdkRGUEhB"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">}</span></span></code></pre> </section> <article data-content="[{"type":"block","id":"7mwv-1723984783507","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"VeJU-1723984783506","leaves":[{"text":"多次根据scroll_id游标查询,直到没有数据返回则结束查询。采用游标查询索引全量数据,更安全高效,限制了单次对内存的消耗。","marks":[]}]}],"state":{}},{"type":"block","id":"9263-1653830250250","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"GPxi-1688026638081","leaves":[{"text":"删除游标scroll","marks":[{"type":"bold"}]}]}],"state":{}},{"type":"block","id":"iIR2-1689926903006","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"ASfG-1689926903004","leaves":[{"text":"scroll超过超时后,搜索上下文会自动删除。然而,保持scroll打开是有代价的,因此一旦不再使用,就应明确清除scroll上下文","marks":[]}]}],"state":{}}]"> <p><span leaf="">多次根据scroll_id游标查询,直到没有数据返回则结束查询。采用游标查询索引全量数据,更安全高效,限制了单次对内存的消耗。</span></p> <p><span style="font-weight: bold;"><span leaf="">删除游标scroll</span></span></p> <p><span leaf="">scroll超过超时后,搜索上下文会自动删除。然而,保持scroll打开是有代价的,因此一旦不再使用,就应明确清除scroll上下文</span></p> </article> <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="bash"><code><span leaf=""><span class="code-snippet__plaintext">DELETE /_search/scroll</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">{</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"scroll_id"</span><span class="code-snippet__plaintext"> : </span><span class="code-snippet__string">"FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFmNwcVdjblRxUzVhZXlicG9HeU02bWcAAAAAAABmzRY2YlV3Z0o5VVNTdWJobkE5Z3MtXzJB"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">}</span></span></code></pre> </section> <article> <h4 yne-bulb-block="heading" yne-bulb-level="4" style="white-space:pre-wrap;line-height:1.75;font-size:14px;text-align:left;"><span style="font-weight: bold;"><span leaf="">scroll查询的优缺点及适用场景</span></span></h4> <p><span style="font-weight: bold;"><span leaf="">scroll查询的优缺点如下:</span></span></p> <ul style="margin:0px;margin-left: 14px;" class="list-paddingleft-1"> <li><span style="font-weight: bold;"><span leaf="">scroll查询优点:</span></span> <section> <span leaf="">支持全量遍历,是检索大量文档的重要方法,但单次遍历的size值不能超过max_result_window的大小。</span> </section></li> <li><span style="font-weight: bold;"><span leaf="">scroll查询缺点:</span></span></li> </ul> <p><span leaf="">scroll查询的适用场景如下:</span></p> <ul style="margin:0px;margin-left: 14px;" class="list-paddingleft-1"> <li> <section> <span leaf="">大量文档检索:当要检索的文档数量很大,甚至需要全量召回数据时,scroll查询是一个很好的选择。</span> </section></li> <li> <section> <span leaf="">大量文档的数据处理:滚动API适合对大量文档进行数据处理,例如索引迁移或将数据导入其他技术栈。</span> </section></li> </ul> <p><span style="color: rgb(243, 50, 50);"><span leaf="">注意:</span></span></p> <p><span leaf="">1) ES7.x之后不建议使用scroll API进行深度分页。</span></p> <p><span leaf="">2) 如果要分页检索并获得超过10000条结果时,则推荐使用search_after。</span></p> <p><span leaf=""><br></span></p> <p><span style="color: rgb(243, 50, 50);"></span></p> <h3 yne-bulb-block="heading" yne-bulb-level="3" style="white-space:pre-wrap;line-height:1.75;font-size:14px;text-align:left;"><span style="font-weight: bold;font-size: inherit;"><span leaf="">search_after查询</span></span></h3> <p><span style="color: rgb(243, 50, 50);"><span leaf="">search_after查询的基本工作原理是以前一页结果的排序值作为参照点,进而检索与这个参照点相邻的下一页的匹配数据。</span></span></p> <p><span leaf="">这种方法在处理大规模数据分页时更为高效且实用。使用该查询的前置条件是要求后续的多个请求返回与第一次查询相同的排序结果序列。也就是说,</span><span style="color: rgb(243, 50, 50);"><span leaf="">在后续翻页的过程中,即便有新数据写入等操作,也不会对原有结果集构成影响。</span></span></p> <p><span leaf="">scroll API适用于高效的深度滚动,但滚动上下文成本高昂,不建议将其用于实时用户请求。而search_after参数通过提供一个活动光标来规避这个问题。这样可以使用上一页的结果来帮助检索下一页。</span></p> <blockquote> <p><span leaf="">官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/8.14/paginate-search-results.html#search-after</span></p> </blockquote> <p><span leaf="">那么,如何实现呢?</span></p> <p><span style="color: rgb(243, 50, 50);"><span leaf="">可以创建一个时间点PIT(Point In Time)来保障在搜索过程中能保留特定事件点的索引状态。</span></span><span leaf="">search_after的后续查询都是基于PIT视图进行的,能有效保障数据的一致性。</span></p> <article data-content="[{"type":"block","id":"eaRk-1723981478698","name":"quote","data":{},"nodes":[{"type":"block","id":"nLBF-1723981475121","name":"paragraph","data":{},"nodes":[{"type":"text","id":"RayY-1723981475119","leaves":[{"text":"PIT是Elasticsearch 7.10版本之后才有的新特性,实际上是存储索引数据状态的轻量级视图。","marks":[]}]}]}],"state":{}},{"type":"block","id":"lu8d-1723981395188","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"y7WA-1723981395187","leaves":[{"text":"","marks":[]}]}],"state":{}}]"> <p><span leaf="">PIT是Elasticsearch 7.10版本之后才有的新特性,实际上是存储索引数据状态的轻量级视图。</span></p> <p><span leaf=""><br></span></p> </article> </article> <article> <h4 yne-bulb-block="heading" yne-bulb-level="4" style="white-space:pre-wrap;line-height:1.75;font-size:14px;text-align:left;"><span style="font-weight: bold;"><span leaf="">实现步骤</span></span></h4> <p><span leaf="">search_after 分页查询可以简单概括为如下几个步骤:</span></p> <p><span style="font-weight: bold;"><span leaf="">1)获取索引的pit</span></span></p> <p><span leaf="">使用 search_after 需要具有相同查询和排序值的多个搜索请求。 如果在这些请求之间发生刷新,结果的顺序可能会发生变化,从而导致跨页面的结果不一致。 为防止出现这种情况,</span><span style="color: rgb(243, 50, 50);"><span leaf="">可以创建一个时间点 (PIT) 以保留搜索中的当前索引状态</span></span><span leaf="">。Point In Time(PIT)是 Elasticsearch 7.10 版本之后才有的新特性</span><span style="color: rgb(77, 77, 77);background-color: rgb(255, 255, 255);font-family: Arial;"><span leaf="">。</span></span></p> </article> <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="swift"><code><span leaf=""><span class="code-snippet__plaintext"># 使用kibana提供的航班测试数据集</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"># 创建一个时间点(</span><span class="code-snippet__type">PIT</span><span class="code-snippet__plaintext">)来保存搜索期间的当前索引状态</span></span></code><code><span leaf=""><span class="code-snippet__type">POST</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__regexp">/kibana_sample_data_flights/</span><span class="code-snippet__plaintext">_pit</span><span class="code-snippet__operator">?</span><span class="code-snippet__plaintext">keep_alive</span><span class="code-snippet__operator">=</span><span class="code-snippet__plaintext">5m</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">#返回结果如下,会返回一个</span><span class="code-snippet__type">PID的值</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">{</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"4YyPBAEaa2liYW5hX3NhbXBsZV9kYXRhX2ZsaWdodHMWZENSdWh0NWNSai1EdUhpcnBCZXgyZwAWTzlaLUtQNTJSNXVON0FxbHZERlBIQQAAAAAAABkI4hZ0OTFBejN3WFJIT0FvNXM2N0VwQ3JBAAEWZENSdWh0NWNSai1EdUhpcnBCZXgyZwAA"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">}</span></span></code></pre> </section> <article> <p><span leaf="">keep_alive=5m是一个类似于scroll的参数,表示滚动视图的保留时间是5min,超过5min Elasticsearch会清除这个滚动视图并报错,如下图所示</span></p> <section nodeleaf=""> <img src="/upload/ddd38ae024262b610c874005b6459e3e.png" class="rich_pages wxw-img" data-ratio="0.2078740157480315" data-type="png" data-w="635" height="132" style="width: 635px;height: 132px;" width="635" data-imgfileid="100000307"> </section> <p><span style="color: rgb(77, 77, 77);background-color: rgb(255, 255, 255);font-size: 14px;font-family: Arial;font-weight: bold;"><span leaf="">2) 根据pit首次查询</span></span></p> <p><span leaf="">创建基础查询语句,主要是设置分页的条件</span></p> </article> <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="bash"><code><span leaf=""><span class="code-snippet__plaintext">GET /_search</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">{</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"query"</span><span class="code-snippet__plaintext">: {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"term"</span><span class="code-snippet__plaintext">: {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"OriginWeather"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"Sunny"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> }</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> },</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"pit"</span><span class="code-snippet__plaintext">: {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"4YyPBAEaa2liYW5hX3NhbXBsZV9kYXRhX2ZsaWdodHMWZENSdWh0NWNSai1EdUhpcnBCZXgyZwAWTzlaLUtQNTJSNXVON0FxbHZERlBIQQAAAAAAABkI4hZ0OTFBejN3WFJIT0FvNXM2N0VwQ3JBAAEWZENSdWh0NWNSai1EdUhpcnBCZXgyZwAA"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"keep_alive"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"1m"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> },</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"size"</span><span class="code-snippet__plaintext">: 10,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"sort"</span><span class="code-snippet__plaintext">: [</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"timestamp"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"asc"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> }</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> ]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">}</span></span></code></pre> </section> <article> <p><span leaf="">代码中设置了PIT,因此检索时候就不需要再指定索引。id是基于第一步返回的id值。排序sort指的是按照哪个关键字排序。</span></p> <p><span leaf="">在每个返回文档的最后会有两个结果值,如下所示:</span></p> <section nodeleaf=""> <img src="/upload/9a4cf81d52a8bd62480279d2c4951618.png" class="rich_pages wxw-img" data-ratio="0.20469798657718122" data-type="png" data-w="596" height="122" style="width: 596px;height: 122px;" width="596" data-imgfileid="100000308"> </section> <p><span leaf="">在每个返回文档的最后会有两个结果值,如下所示。</span></p> <p><span leaf="">其中,1723434063000就是我们指定的排序方式,所以上述示例是基于{"timestamp": "asc"}升序排列的。130代表隐含的排序值,官方文档把这种隐含的字段叫作tiebreaker(决胜字段),tiebreaker代表了每个文档的唯一值,确保分页不会丢失或者分页结果数据出现重复(包括相同页重复和跨页重复)。</span></p> <p><span style="color: rgb(77, 77, 77);background-color: rgb(255, 255, 255);font-size: inherit;font-family: Arial;font-weight: bold;"><span leaf="">3)</span></span><span style="font-size: inherit;font-weight: bold;"><span leaf="">根据search_after和pit实现后续翻页。</span></span></p> <p><span leaf="">要获得下一页结果,请使用最后一次命中的排序值(包括 tiebreaker)作为 search_after 参数重新运行先前的搜索。 如果使用 PIT,请在 pit.id 参数中使用最新的 PIT ID。 搜索的查询和排序参数必须保持不变。</span></p> </article> <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="cpp"><code><span leaf=""><span class="code-snippet__plaintext">#后续翻页都需要借助search_after来指定前一页中最后一个文档的sort字段值</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">GET /_search</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">{</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"query"</span><span class="code-snippet__plaintext">: {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"term"</span><span class="code-snippet__plaintext">: {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"OriginWeather"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"Sunny"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> }</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> },</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"pit"</span><span class="code-snippet__plaintext">: {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"4YyPBAEaa2liYW5hX3NhbXBsZV9kYXRhX2ZsaWdodHMWZENSdWh0NWNSai1EdUhpcnBCZXgyZwAWTzlaLUtQNTJSNXVON0FxbHZERlBIQQAAAAAAABkI4hZ0OTFBejN3WFJIT0FvNXM2N0VwQ3JBAAEWZENSdWh0NWNSai1EdUhpcnBCZXgyZwAA"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"keep_alive"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"5m"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> },</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"size"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">10</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"sort"</span><span class="code-snippet__plaintext">: [</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"timestamp"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"asc"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> }</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> ],</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"search_after"</span><span class="code-snippet__plaintext">: [</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1723434063000</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">130</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> ]</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">}</span></span></code></pre> </section> <article> <p><span style="color: rgb(243, 50, 50);"><span leaf="">显然,search_after查询仅支持向后翻页。</span></span></p> <h4 yne-bulb-block="heading" yne-bulb-level="4" style="white-space:pre-wrap;line-height:1.75;font-size:14px;text-align:left;"><span style="font-weight: bold;"><span leaf="">优缺点</span></span></h4> <p><span style="font-weight: bold;"><span leaf="">search_after优点:</span></span></p> <ul style="margin:0px;margin-left: 14px;" class="list-paddingleft-1"> <li> <section> <span leaf="">不严格受制于max_result_window,可以无限地往后翻页。此处的“不严格”是指单次请求值不能超过max_result_window,但总翻页结果集可以超过。</span> </section></li> </ul> <p><span style="font-weight: bold;"><span leaf="">search_after缺点:</span></span></p> <ul style="margin:0px;margin-left: 14px;" class="list-paddingleft-1"> <li> <section> <span leaf="">只支持向后翻页,不支持随机翻页。search_after不支持随机翻页,更适合在手机端应用的场景中使用,类似今日头条等产品的分页搜索。</span> </section></li> </ul> <p><span style="color: rgb(77, 77, 77);background-color: rgb(255, 255, 255);font-size: inherit;font-family: Arial;"></span></p> <h2 yne-bulb-block="heading" yne-bulb-level="2" style="white-space:pre-wrap;line-height:1.75;font-size:14px;text-align:left;"><span style="font-weight: bold;font-size: 20px;"><span leaf="">4. ES三种分页方式总结</span></span></h2> <table style="border-collapse:collapse;table-layout:fixed;white-space:nowrap;width:0;"> <caption> <section> <span leaf=""><br></span> </section> </caption> <tfoot> <tr> <td valign="top"> <section> <span leaf=""><br></span> </section></td> </tr> </tfoot> </table> <table> <tbody> <tr style="height: 40px;"> <td valign="top" style="background-color:rgb(240, 240, 240);border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">分页方式</span></span></p></td> <td valign="top" style="background-color:rgb(240, 240, 240);border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">性能</span></span></p></td> <td valign="top" style="background-color:rgb(240, 240, 240);border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">优点</span></span></p></td> <td valign="top" style="background-color:rgb(240, 240, 240);border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">缺点</span></span></p></td> <td valign="top" style="background-color:rgb(240, 240, 240);border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">适用场景</span></span></p></td> </tr> <tr style="height: 40px;"> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">from + size</span></span></p></td> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">低</span></span></p></td> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">支持随机翻页</span></span></p></td> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">受制于max_result_window设置,不能无限制翻页;</span></span></p><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">存在深度翻译问题,越往后翻译越慢。</span></span></p></td> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">需要随机跳转不同页(PC端主流搜索引擎); 在10000条数据之内分页显示</span></span></p></td> </tr> <tr style="height: 78px;"> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">scroll</span></span></p></td> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">中</span></span></p></td> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">支持全量遍历,但单次遍历的size值不能超过max_result_window的大小</span></span></p></td> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">响应是非实时的;保留上下文需要具有足够的堆内存空间;需要通过更多的网络请求才能获取所有结果。</span></span></p></td> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">需要遍历全量数据</span></span></p></td> </tr> <tr style="height: 40px;"> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">search_after</span></span></p></td> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">高</span></span></p></td> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">不严格受制于max_result_window,可以无限地往后翻页。</span></span></p></td> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">只支持向后翻页,不支持随机翻页。</span></span></p></td> <td valign="top" style="border:1px solid rgb(167, 167, 167);overflow:hidden;font-size:14px;overflow-wrap:break-word;white-space:pre-wrap;color:rgb(57, 57, 57);"><p><span style="font-family: Microsoft YaHei, STXihei;background-color: rgba(0, 0, 0, 0);font-size: 14px;color: rgb(0, 0, 0);"><span leaf="">仅需要向后翻页;超过10000条数据,需要分页</span></span></p></td> </tr> </tbody> </table> </article>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 10px;padding-right: 10px;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;font-family: Optima, 'Microsoft YaHei', PingFangSC-regular, serif;font-size: 16px;color: rgb(0, 0, 0);line-height: 1.5em;word-spacing: 0em;letter-spacing: 0em;word-break: break-word;overflow-wrap: break-word;text-align: left;"> <h1 data-tool="mdnice编辑器" style=" align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: center;line-height: 1.5em;margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px; text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span data-cacheurl="" data-remoteid="" style="background-attachment: scroll;background-clip: border-box;background-color: transparent;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: contain;width: 30px;height: auto;align-items: unset;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;color: rgb(0, 0, 0);display: block;font-size: 22px;font-weight: bold;font-style: normal;flex-direction: unset;float: unset;justify-content: unset;letter-spacing: 0em;line-height: 1.5em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px; text-align: left;text-indent: 0em;text-shadow: none;transform: none;-webkit-box-reflect: unset;background-image: url(" https: mmbiz.qpic.cn sz_mmbiz_png ibyr7oxjrfgx83b9rloaxlqftamoykiaah6ysulvk0tqegnvyggiadwqmng8uffvfkd2obommmpmx0r7muzvqhazw 640?wx_fmt="png&from=appmsg");""></span><span style=" font-size: 22px;line-height: 1.8em;letter-spacing: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 10px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: linear-gradient(0deg, rgb(231, 247, 252) 40%, transparent 40%);background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;color: rgb(112, 188, 234);display: block;font-weight: bold;font-style: normal;flex-direction: unset;float: unset;height: auto;justify-content: unset;overflow-x: unset;overflow-y: unset; text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span leaf="">解密主流框架中的Netty应用</span></span><span style="display: none;"></span></h1> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">大家好,今天我要和大家分享一个有趣的话题:那些著名的开源框架是如何使用Netty的。这些年我在研究这些框架源码的过程中,发现了很多精妙的设计。让我们一起来扒一扒他们的"老底"。</span></p> <h2 data-tool="mdnice编辑器" style=" border-bottom-color: rgb(239, 112, 96);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.1em;overflow-x: unset;overflow-y: unset; text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span style="display: none;"></span><span style=" font-size: 22px;color: rgb(255, 255, 255);background-color: rgb(239, 112, 96);line-height: 1.5em;letter-spacing: 0em;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 3px;border-top-right-radius: 3px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 5px;overflow-x: unset;overflow-y: unset;padding-top: 3px;padding-bottom: 1px;padding-left: 10px;padding-right: 10px; text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span leaf="">RocketMQ:消息队列的艺术</span></span><span style="display: none;"></span><span style=" border-bottom-color: rgb(239, 235, 233);align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: solid;border-top-width: 1px;border-bottom-width: 36px;border-left-width: 1px;border-right-width: 20px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: transparent;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;color: rgb(0, 0, 0);display: inline-block;font-size: 16px;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;letter-spacing: 0px;line-height: 1.1em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px; text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">先说说RocketMQ。作为阿里开源的消息中间件,它的网络层完全基于Netty构建。为什么这么说?让我给大家看点有意思的代码。</span></p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: block;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(0, 0, 0);line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: bold;display: block;"><span leaf="">网络层设计</span></span><span style="display: none;"></span></h3> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg axupzvuyfjydeegicmbjgcsrlqhlfivpiaxhiowogar3ktbib4apblgvwdcbwusecab0qus2w0hwhozmc3a48xxxbcmohigunpy 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">NettyRemotingServer</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">private</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">final</span></span><span leaf=""> ServerBootstrap serverBootstrap;</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">private</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">final</span></span><span leaf=""> EventLoopGroup bossGroup;</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">private</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">final</span></span><span leaf=""> EventLoopGroup workerGroup;</span><br><span leaf=""> </span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">NettyRemotingServer</span></span><span style="line-height: 26px;"><span leaf="">()</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">this</span></span><span leaf="">.serverBootstrap = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> ServerBootstrap();</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// boss就配一个线程,够用了</span></span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">this</span></span><span leaf="">.bossGroup = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> NioEventLoopGroup(</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1</span></span><span leaf="">, </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> ThreadFactoryImpl(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"NettyBossSelector_"</span></span><span leaf="">));</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// worker线程看配置和压力来定</span></span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">this</span></span><span leaf="">.workerGroup = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> NioEventLoopGroup(</span><br><span leaf=""> NettyServerConfig.getServerWorkerThreads(),</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> ThreadFactoryImpl(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"NettyServerWorkerSelector_"</span></span><span leaf="">)</span><br><span leaf=""> );</span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">有意思的是,RocketMQ把网络层抽象得特别好。记得有次我们要基于RocketMQ做二次开发,就特别感激它这种设计:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg axupzvuyfjydeegicmbjgcsrlqhlfivpiaxhiowogar3ktbib4apblgvwdcbwusecab0qus2w0hwhozmc3a48xxxbcmohigunpy 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 请求-响应模型</span></span><br><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">RequestProcessor</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> RemotingCommand </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">processRequest</span></span><span style="line-height: 26px;"><span leaf="">(ChannelHandlerContext ctx, RemotingCommand request)</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 1. 生成请求ID,保证请求唯一性</span></span><br><span leaf=""> request.setOpaque(requestId.getAndIncrement());</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 2. 创建响应Future</span></span><br><span leaf=""> ResponseFuture responseFuture = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> ResponseFuture(request.getOpaque(),</span><br><span leaf=""> timeoutMillis);</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 3. 发送请求</span></span><br><span leaf=""> channel.writeAndFlush(request);</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 4. 等待响应</span></span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> responseFuture.waitResponse();</span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">RocketMQ的这套设计教会我们:</span></p> <ol style="list-style-type: decimal;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">网络层要做好抽象,方便扩展</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">请求-响应要支持超时和异步</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">连接管理要做到优雅和高效</span> </section></li> </ol> <h2 data-tool="mdnice编辑器" style=" border-bottom-color: rgb(239, 112, 96);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.1em;overflow-x: unset;overflow-y: unset; text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span style="display: none;"></span><span style=" font-size: 22px;color: rgb(255, 255, 255);background-color: rgb(239, 112, 96);line-height: 1.5em;letter-spacing: 0em;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 3px;border-top-right-radius: 3px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 5px;overflow-x: unset;overflow-y: unset;padding-top: 3px;padding-bottom: 1px;padding-left: 10px;padding-right: 10px; text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span leaf="">Dubbo:RPC的智慧</span></span><span style="display: none;"></span><span style=" border-bottom-color: rgb(239, 235, 233);align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: solid;border-top-width: 1px;border-bottom-width: 36px;border-left-width: 1px;border-right-width: 20px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: transparent;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;color: rgb(0, 0, 0);display: inline-block;font-size: 16px;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;letter-spacing: 0px;line-height: 1.1em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px; text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">说到Dubbo,它可是把Netty用得出神入化。虽然Dubbo支持多种通信框架,但Netty是它的默认选择,而且是最成熟的实现。</span></p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: block;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(0, 0, 0);line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: bold;display: block;"><span leaf="">多协议支持</span></span><span style="display: none;"></span></h3> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg axupzvuyfjydeegicmbjgcsrlqhlfivpiaxhiowogar3ktbib4apblgvwdcbwusecab0qus2w0hwhozmc3a48xxxbcmohigunpy 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">NettyServer</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">doOpen</span></span><span style="line-height: 26px;"><span leaf="">()</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> bootstrap = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> ServerBootstrap();</span><br><span leaf=""> </span><br><span leaf=""> bossGroup = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> NioEventLoopGroup(</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1</span></span><span leaf="">);</span><br><span leaf=""> workerGroup = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> NioEventLoopGroup(getUrl().getPositiveParameter(</span><br><span leaf=""> Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS));</span><br><span leaf=""> </span><br><span leaf=""> bootstrap.group(bossGroup, workerGroup)</span><br><span leaf=""> .channel(NioServerSocketChannel</span><span style="line-height: 26px;"><span leaf="">.</span><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf="">)</span><br><span leaf=""> .</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">childHandler</span></span><span leaf="">(</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">ChannelInitializer</span></span><span leaf=""><</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">NioSocketChannel</span></span><span leaf="">>() </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">protected</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">initChannel</span></span><span style="line-height: 26px;"><span leaf="">(NioSocketChannel ch)</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 这个Pipeline设计得很赞</span></span><br><span leaf=""> ChannelPipeline pipeline = ch.pipeline();</span><br><span leaf=""> pipeline.addLast(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"decoder"</span></span><span leaf="">, </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> DubboCodec());</span><br><span leaf=""> pipeline.addLast(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"handler"</span></span><span leaf="">, </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> HeaderExchangeHandler());</span><br><span leaf=""> }</span><br><span leaf=""> });</span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">有趣的是Dubbo的编解码器设计:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg axupzvuyfjydeegicmbjgcsrlqhlfivpiaxhiowogar3ktbib4apblgvwdcbwusecab0qus2w0hwhozmc3a48xxxbcmohigunpy 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">DubboCodec</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">extends</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">ByteToMessageDecoder</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">protected</span></span><span leaf=""> Object </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">decode</span></span><span style="line-height: 26px;"><span leaf="">(Channel channel, ByteBuf input)</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">byte</span></span><span leaf="">[] header = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">byte</span></span><span leaf="">[</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">16</span></span><span leaf="">];</span><br><span leaf=""> input.readBytes(header);</span><br><span leaf=""> </span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// Dubbo的魔数检查,这个设计我们可以学习</span></span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> (header[</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0</span></span><span leaf="">] != MAGIC_HIGH || header[</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1</span></span><span leaf="">] != MAGIC_LOW) {</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throw</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> IOException(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Error magic number!"</span></span><span leaf="">);</span><br><span leaf=""> }</span><br><span leaf=""> </span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 解析协议版本、请求类型等</span></span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> decodebody(...);</span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <h2 data-tool="mdnice编辑器" style=" border-bottom-color: rgb(239, 112, 96);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.1em;overflow-x: unset;overflow-y: unset; text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span style="display: none;"></span><span style=" font-size: 22px;color: rgb(255, 255, 255);background-color: rgb(239, 112, 96);line-height: 1.5em;letter-spacing: 0em;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 3px;border-top-right-radius: 3px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 5px;overflow-x: unset;overflow-y: unset;padding-top: 3px;padding-bottom: 1px;padding-left: 10px;padding-right: 10px; text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span leaf="">Spring WebFlux:响应式的艺术</span></span><span style="display: none;"></span><span style=" border-bottom-color: rgb(239, 235, 233);align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: solid;border-top-width: 1px;border-bottom-width: 36px;border-left-width: 1px;border-right-width: 20px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: transparent;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;color: rgb(0, 0, 0);display: inline-block;font-size: 16px;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;letter-spacing: 0px;line-height: 1.1em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px; text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">WebFlux是Spring 5引入的响应式Web框架,它的底层网络也是用的Netty。说实话,它对Netty的使用特别优雅。</span></p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: block;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(0, 0, 0);line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: bold;display: block;"><span leaf="">响应式处理</span></span><span style="display: none;"></span></h3> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg axupzvuyfjydeegicmbjgcsrlqhlfivpiaxhiowogar3ktbib4apblgvwdcbwusecab0qus2w0hwhozmc3a48xxxbcmohigunpy 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">HttpServerRoutes</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> RouterFunction <serverresponse> route = RouterFunctions </serverresponse></span><br><span leaf=""> .route(GET(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"/hello"</span></span><span leaf="">), </span><br><span leaf=""> request -> ServerResponse.ok()</span><br><span leaf=""> .body(Mono.just(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Hello, Reactive!"</span></span><span leaf="">), String</span><span style="line-height: 26px;"><span leaf="">.</span><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf="">))</span><br><span leaf=""> .</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">andRoute</span></span><span leaf="">(</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">POST</span></span><span leaf="">("/</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">upload</span></span><span leaf="">"), </span><br><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">request</span></span><span leaf=""> -> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">request</span></span><span leaf="">.</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">bodyToFlux</span></span><span leaf="">(</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">DataBuffer</span></span><span leaf="">.</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">class</span></span><span leaf="">)</span><br><span leaf=""> .</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">map</span></span><span leaf="">(</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">buffer</span></span><span leaf=""> -> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">handleBuffer</span></span><span leaf="">(</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">buffer</span></span><span leaf="">))</span><br><span leaf=""> .</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">then</span></span><span leaf="">(</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">ServerResponse</span></span><span leaf="">.</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">ok</span></span><span leaf="">().</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">build</span></span><span leaf="">()))</span></span><span leaf="">;</span><br><span leaf="">}</span><br></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">WebFlux是怎么和Netty配合的?看这段代码:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg axupzvuyfjydeegicmbjgcsrlqhlfivpiaxhiowogar3ktbib4apblgvwdcbwusecab0qus2w0hwhozmc3a48xxxbcmohigunpy 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">ReactorHttpHandlerAdapter</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">extends</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">ChannelInboundHandlerAdapter</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">channelRead</span></span><span style="line-height: 26px;"><span leaf="">(ChannelHandlerContext ctx, Object msg)</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> (msg </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">instanceof</span></span><span leaf=""> HttpRequest) {</span><br><span leaf=""> HttpRequest request = (HttpRequest) msg;</span><br><span leaf=""> NettyServerHttpRequest adaptedRequest = </span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> NettyServerHttpRequest(ctx, request);</span><br><span leaf=""> </span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 转换成响应式流处理</span></span><br><span leaf=""> handle(adaptedRequest)</span><br><span leaf=""> .doOnSuccess(response -> </span><br><span leaf=""> response.writeWith(Flux.just(buffer))</span><br><span leaf=""> .subscribe())</span><br><span leaf=""> .subscribe();</span><br><span leaf=""> }</span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这里面有很多值得学习的设计:</span></p> <ol style="list-style-type: decimal;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">适配器模式的巧妙运用</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">响应式流与Netty的完美结合</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">非阻塞式的请求处理</span> </section></li> </ol> <h2 data-tool="mdnice编辑器" style=" border-bottom-color: rgb(239, 112, 96);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.1em;overflow-x: unset;overflow-y: unset; text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span style="display: none;"></span><span style=" font-size: 22px;color: rgb(255, 255, 255);background-color: rgb(239, 112, 96);line-height: 1.5em;letter-spacing: 0em;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 3px;border-top-right-radius: 3px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 5px;overflow-x: unset;overflow-y: unset;padding-top: 3px;padding-bottom: 1px;padding-left: 10px;padding-right: 10px; text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span leaf="">Elasticsearch:搜索引擎的秘密</span></span><span style="display: none;"></span><span style=" border-bottom-color: rgb(239, 235, 233);align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: solid;border-top-width: 1px;border-bottom-width: 36px;border-left-width: 1px;border-right-width: 20px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: transparent;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;color: rgb(0, 0, 0);display: inline-block;font-size: 16px;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;letter-spacing: 0px;line-height: 1.1em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px; text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">ES的集群间通信也是用Netty实现的。它的实现特别有特色:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg axupzvuyfjydeegicmbjgcsrlqhlfivpiaxhiowogar3ktbib4apblgvwdcbwusecab0qus2w0hwhozmc3a48xxxbcmohigunpy 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">Netty4Transport</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">extends</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">TcpTransport</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">protected</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">doStart</span></span><span style="line-height: 26px;"><span leaf="">()</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> bootstrap = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> ServerBootstrap();</span><br><span leaf=""> bootstrap.group(</span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> NioEventLoopGroup(settings.get(WORKER_COUNT)))</span><br><span leaf=""> .channel(NioServerSocketChannel</span><span style="line-height: 26px;"><span leaf="">.</span><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf="">)</span><br><span leaf=""> .</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">childHandler</span></span><span leaf="">(</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">ChannelInitializer</span></span><span leaf=""><</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">Channel</span></span><span leaf="">>() </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">protected</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">initChannel</span></span><span style="line-height: 26px;"><span leaf="">(Channel ch)</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 看看这个Pipeline的设计</span></span><br><span leaf=""> ch.pipeline()</span><br><span leaf=""> .addLast(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"ssl"</span></span><span leaf="">, </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> SslHandler())</span><br><span leaf=""> .addLast(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"size"</span></span><span leaf="">, </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> MessageSizeHandler())</span><br><span leaf=""> .addLast(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"compress"</span></span><span leaf="">, </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> MessageCompressionHandler())</span><br><span leaf=""> .addLast(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"dispatcher"</span></span><span leaf="">, </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> MessageDispatcher());</span><br><span leaf=""> }</span><br><span leaf=""> });</span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">ES的这套网络架构教会我们:</span></p> <ol style="list-style-type: decimal;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">安全性要放在第一位(SSL)</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">消息压缩很重要</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">分发机制要设计好</span> </section></li> </ol> <h2 data-tool="mdnice编辑器" style=" border-bottom-color: rgb(239, 112, 96);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.1em;overflow-x: unset;overflow-y: unset; text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span style="display: none;"></span><span style=" font-size: 22px;color: rgb(255, 255, 255);background-color: rgb(239, 112, 96);line-height: 1.5em;letter-spacing: 0em;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 3px;border-top-right-radius: 3px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 5px;overflow-x: unset;overflow-y: unset;padding-top: 3px;padding-bottom: 1px;padding-left: 10px;padding-right: 10px; text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span leaf="">经验总结</span></span><span style="display: none;"></span><span style=" border-bottom-color: rgb(239, 235, 233);align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: solid;border-top-width: 1px;border-bottom-width: 36px;border-left-width: 1px;border-right-width: 20px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: transparent;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;color: rgb(0, 0, 0);display: inline-block;font-size: 16px;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;letter-spacing: 0px;line-height: 1.1em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px; text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">研究这些框架的源码,我学到了很多:</span></p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: block;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(0, 0, 0);line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: bold;display: block;"><span leaf="">1. 协议设计</span></span><span style="display: none;"></span></h3> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">使用魔数标识协议</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">预留版本号字段</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">支持协议扩展</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">考虑向后兼容</span> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: block;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(0, 0, 0);line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: bold;display: block;"><span leaf="">2. 性能优化</span></span><span style="display: none;"></span></h3> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">池化技术的运用</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">零拷贝的使用</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">内存管理的重要性</span> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: block;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(0, 0, 0);line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: bold;display: block;"><span leaf="">3. 可靠性保障</span></span><span style="display: none;"></span></h3> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">心跳机制的实现</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">优雅的重连策略</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">异常处理的完整性</span> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: block;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(0, 0, 0);line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: bold;display: block;"><span leaf="">4. 代码设计</span></span><span style="display: none;"></span></h3> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">接口抽象要合理</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">组件职责要单一</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">扩展性要考虑周全</span> </section></li> </ul> <h2 data-tool="mdnice编辑器" style=" border-bottom-color: rgb(239, 112, 96);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.1em;overflow-x: unset;overflow-y: unset; text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span style="display: none;"></span><span style=" font-size: 22px;color: rgb(255, 255, 255);background-color: rgb(239, 112, 96);line-height: 1.5em;letter-spacing: 0em;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 3px;border-top-right-radius: 3px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 5px;overflow-x: unset;overflow-y: unset;padding-top: 3px;padding-bottom: 1px;padding-left: 10px;padding-right: 10px; text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "><span leaf="">写在最后</span></span><span style="display: none;"></span><span style=" border-bottom-color: rgb(239, 235, 233);align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: solid;border-top-width: 1px;border-bottom-width: 36px;border-left-width: 1px;border-right-width: 20px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: transparent;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;color: rgb(0, 0, 0);display: inline-block;font-size: 16px;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;letter-spacing: 0px;line-height: 1.1em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px; text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset; "></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">回顾这些框架对Netty的使用,能看出它们都有各自的特点:</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">RocketMQ注重性能和可靠性</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">Dubbo强调协议的扩展性</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">WebFlux追求响应式处理</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <span leaf="">ES重视安全性和压缩处理</span> </section></li> </ul> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这些设计思路都值得我们学习。说实话,看这些优秀的开源项目源码,就像在和高手过招,每次都能学到新东西。</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">你们在看这些框架源码时,有没有发现什么有趣的设计?欢迎在评论区分享你的发现!</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">至此,我们的Netty系列就告一段落了。回顾这些文章,我们从NIO聊到Netty,从原理聊到实践,从基础组件聊到开源框架,算是对Netty有了一个全面的认识。希望这些内容对大家有帮助!</span></p> </section>
作者:微信小助手
<p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(119, 119, 119);font-size: 14px;"><span leaf=""><span textstyle="" style="font-weight: bold;">记录20亿的用户连续 7 天的打卡数据,如何统计出这连续 7 天连续打卡用户总数呢?</span></span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">我们把每天的日期作为 Bitmap 的 key,userId 作为 offset,若是打卡则将 offset 位置的 bit 设置成 1。</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">key 对应的集合的每个 bit 位的数据则是一个用户在该日期的打卡记录。</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">一共有 7 个这样的 Bitmap,如果我们能对这 7 个 Bitmap 的对应的 bit 位做 『与』运算。</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">同样的 UserID offset 都是一样的,当一个 userID 在 7 个 Bitmap 对应对应的 offset 位置的 bit = 1 就说明该用户 7 天连续打卡。</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">结果保存到一个新 Bitmap 中,我们再通过</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(10, 191, 91);background-color: rgb(243, 245, 249);font-size: 14px;"><span leaf="">BITCOUNT</span></span></code><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">统计 bit = 1 的个数便得到了连续打卡 7 天的用户总数了。</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">Redis 提供了</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(10, 191, 91);background-color: rgb(243, 245, 249);font-size: 14px;"><span leaf="">BITOP operation destkey key [key ...]</span></span></code><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">这个指令用于对一个或者多个 键 = key 的 Bitmap 进行位元操作。</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(10, 191, 91);background-color: rgb(243, 245, 249);font-size: 14px;"><span leaf="">opration</span></span></code><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">可以是</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(10, 191, 91);background-color: rgb(243, 245, 249);font-size: 14px;"><span leaf="">and</span></span></code><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">、</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(10, 191, 91);background-color: rgb(243, 245, 249);font-size: 14px;"><span leaf="">OR</span></span></code><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">、</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(10, 191, 91);background-color: rgb(243, 245, 249);font-size: 14px;"><span leaf="">NOT</span></span></code><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">、</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(10, 191, 91);background-color: rgb(243, 245, 249);font-size: 14px;"><span leaf="">XOR</span></span></code><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">。当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(10, 191, 91);background-color: rgb(243, 245, 249);font-size: 14px;"><span leaf="">0</span></span></code><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">。空的</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(10, 191, 91);background-color: rgb(243, 245, 249);font-size: 14px;"><span leaf="">key</span></span></code><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">也被看作是包含</span></span><code style="font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace;background-color: rgba(0, 0, 0, 0.06);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 2px;padding: 0px 2px;"><span style="color: rgb(10, 191, 91);background-color: rgb(243, 245, 249);font-size: 14px;"><span leaf="">0</span></span></code><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">的字符串序列。</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">便于理解,如下图所示:</span></span></p> <section style="text-align: center;" nodeleaf=""> <img src="/upload/b74ba622c44b63dc5ab2d535859e2abd.png" class="rich_pages wxw-img" data-ratio="0.362962962962963" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100000621"> </section> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">3 个 Bitmap,对应的 bit 位做「与」操作,结果保存到新的 Bitmap 中。</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">操作指令表示将 三个 bitmap 进行 AND 操作,并将结果保存到 destmap 中。接着对 destmap 执行 BITCOUNT 统计。</span></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="javascript"><code><span leaf=""><span class="code-snippet__comment">// 与操作</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">BITOP AND destmap bitmap:01 bitmap:02 bitmap:03</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">// 统计 bit 位 = 1 的个数</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">BITCOUNT destmap</span></span></code></pre> </section><ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u559edf80%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u6d6bcd9a%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(51%2C%2051%2C%2051)%22%2C%22fontsize%22%3A14%7D%2C%22data%22%3A%22%E7%AE%80%E5%8D%95%E8%AE%A1%E7%AE%97%E4%B8%8B%20%E4%B8%80%E4%B8%AA%E4%B8%80%E4%BA%BF%E4%B8%AA%E4%BD%8D%E7%9A%84%20Bitmap%E5%8D%A0%E7%94%A8%E7%9A%84%E5%86%85%E5%AD%98%E5%BC%80%E9%94%80%EF%BC%8C%E5%A4%A7%E7%BA%A6%E5%8D%A0%2012%20MB%20%E7%9A%84%E5%86%85%E5%AD%98%EF%BC%8810%5E8%2F8%2F1024%2F1024%EF%BC%89%EF%BC%8C7%20%E5%A4%A9%E7%9A%84%20Bitmap%20%E7%9A%84%E5%86%85%E5%AD%98%E5%BC%80%E9%94%80%E7%BA%A6%E4%B8%BA%2084%20MB%E3%80%82%E5%90%8C%E6%97%B6%E6%88%91%E4%BB%AC%E6%9C%80%E5%A5%BD%E7%BB%99%20Bitmap%20%E8%AE%BE%E7%BD%AE%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%EF%BC%8C%E8%AE%A9%20Redis%20%E5%88%A0%E9%99%A4%E8%BF%87%E6%9C%9F%E7%9A%84%E6%89%93%E5%8D%A1%E6%95%B0%E6%8D%AE%EF%BC%8C%E8%8A%82%E7%9C%81%E5%86%85%E5%AD%98%E3%80%82%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fypgse0xcb95ww30v"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">简单计算下 一个一亿个位的 Bitmap占用的内存开销,大约占 12 MB 的内存(10^8/8/1024/1024),7 天的 Bitmap 的内存开销约为 84 MB。同时我们最好给 Bitmap 设置过期时间,让 Redis 删除过期的打卡数据,节省内存。</span></span></p><ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ub9805d7d%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u8c693aa8%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(51%2C%2051%2C%2051)%22%2C%22fontsize%22%3A14%7D%2C%22data%22%3A%22%E7%A4%BA%E4%BE%8B%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fypgse0xcb95ww30v"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf=""><span textstyle="" style="font-weight: bold;">示例</span></span></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="bash"><code><span leaf=""><span class="code-snippet__comment"># 假设有3个用户(ID: 1001,1002,1003)在3天内的打卡记录 </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"># 第一天打卡记录 bitmap:20241213 </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">SETBIT bitmap:20241213 1001 1 # 用户1001打卡 </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">SETBIT bitmap:20241213 1002 1 # 用户1002打卡 </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">SETBIT bitmap:20241213 1003 0 # 用户1003未打卡 </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"># 第二天打卡记录 bitmap:20241214 </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">SETBIT bitmap:20241214 1001 1 # 用户1001打卡 </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">SETBIT bitmap:20241214 1002 0 # 用户1002未打卡 </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">SETBIT bitmap:20241214 1003 1 # 用户1003打卡 </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"># 第三天打卡记录 bitmap:20241215 </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">SETBIT bitmap:20241215 1001 1 # 用户1001打卡 </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">SETBIT bitmap:20241215 1002 1 # 用户1002打卡 </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">SETBIT bitmap:20241215 1003 1 # 用户1003打卡 </span></span></code></pre> </section><ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ue02c362a%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ub8414eb0%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgba(6%2C%208%2C%2031%2C%200.88)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E7%8E%B0%E5%9C%A8%E5%88%86%E6%9E%90%E6%AF%8F%E4%B8%AA%E7%94%A8%E6%88%B7%E7%9A%84%E6%83%85%E5%86%B5%EF%BC%9A%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fypgse0xcb95ww30v"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgba(6, 8, 31, 0.88);font-size: 16px;"><span leaf="">现在分析每个用户的情况:</span></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=""><code><span leaf=""><span class="code-snippet__plaintext">用户1001的打卡记录:1 1 1 (连续打卡) </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">用户1002的打卡记录:1 0 1 (没有连续打卡) </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">用户1003的打卡记录:0 1 1 (没有连续打卡)</span></span></code></pre> </section><ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u213074f7%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ube21c1f1%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgba(6%2C%208%2C%2031%2C%200.88)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E6%89%A7%E8%A1%8CBITOP%20AND%E6%93%8D%E4%BD%9C%EF%BC%9A%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fypgse0xcb95ww30v"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgba(6, 8, 31, 0.88);font-size: 16px;"><span leaf="">执行BITOP AND操作:</span></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="bash"><code><span leaf=""><span class="code-snippet__comment"># 对三天的bitmap进行与运算,结果存入destmap </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">BITOP AND destmap bitmap:20241213 bitmap:20241214 bitmap:20241215 </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext"># 结果分析: </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">用户1001: 1 AND 1 AND 1 = 1 (在destmap中是1) </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">用户1002: 1 AND 0 AND 1 = 0 (在destmap中是0) </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">用户1003: 0 AND 1 AND 1 = 0 (在destmap中是0)</span></span></code></pre> </section><ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u884f24d3%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u1ff7a0dd%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgba(6%2C%208%2C%2031%2C%200.88)%22%2C%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E7%BB%9F%E8%AE%A1%E8%BF%9E%E7%BB%AD%E6%89%93%E5%8D%A1%E7%94%A8%E6%88%B7%E6%95%B0%EF%BC%9A%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fypgse0xcb95ww30v"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgba(6, 8, 31, 0.88);font-size: 16px;"><span leaf="">统计连续打卡用户数:</span></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="bash"><code><span leaf=""><span class="code-snippet__comment"># 统计destmap中1的个数 </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">BITCOUNT destmap # 结果为1,表示只有用户1001连续打卡</span></span></code></pre> </section> <section style="text-align: center;" nodeleaf=""> <img src="/upload/c6b9812ee5b2f56923e988d6db62ba38.png" class="rich_pages wxw-img" data-ratio="0.5685185185185185" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100000622"> </section><ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%22ubc538e0e%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22uf9520d78%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22fontsize%22%3A16%7D%2C%22data%22%3A%22%E5%88%86%E6%9E%90%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fypgse0xcb95ww30v"></ne-clipboard> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-weight: bold;">分析</span></span></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 leaf=""><span class="code-snippet__plaintext">三天的打卡记录可以表示为: </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__keyword">offset</span><span class="code-snippet__plaintext">(用户ID): </span><span class="code-snippet__number">1001</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1002</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1003</span><span class="code-snippet__plaintext"> </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">第一天: </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> (bitmap:</span><span class="code-snippet__number">20241213</span><span class="code-snippet__plaintext">) </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">第二天: </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> (bitmap:</span><span class="code-snippet__number">20241214</span><span class="code-snippet__plaintext">) </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">第三天: </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> (bitmap:</span><span class="code-snippet__number">20241215</span><span class="code-snippet__plaintext">) </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">执行BITOP </span><span class="code-snippet__keyword">AND</span><span class="code-snippet__plaintext">操作: </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">BITOP </span><span class="code-snippet__keyword">AND</span><span class="code-snippet__plaintext"> destmap bitmap:</span><span class="code-snippet__number">20241213</span><span class="code-snippet__plaintext"> bitmap:</span><span class="code-snippet__number">20241214</span><span class="code-snippet__plaintext"> bitmap:</span><span class="code-snippet__number">20241215</span><span class="code-snippet__plaintext"> </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">计算过程: </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">用户</span><span class="code-snippet__number">1001</span><span class="code-snippet__plaintext">的位置: </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">AND</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">AND</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">=</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> (三天都打卡) </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">用户</span><span class="code-snippet__number">1002</span><span class="code-snippet__plaintext">的位置: </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">AND</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">AND</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">=</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> (第二天没打卡) </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">用户</span><span class="code-snippet__number">1003</span><span class="code-snippet__plaintext">的位置: </span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">AND</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">AND</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__operator">=</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> (第一天没打卡) </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">最终destmap的结果: </span></span></code><code><span leaf=""><span class="code-snippet__keyword">offset</span><span class="code-snippet__plaintext">(用户ID): </span><span class="code-snippet__number">1001</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1002</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">1003</span><span class="code-snippet__plaintext"> </span></span></code><code><span leaf=""><span class="code-snippet__plaintext">destmap: </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> </span></span></code><code><span leaf=""><br></span></code><code><span leaf=""><span class="code-snippet__plaintext">当执行 BITCOUNT destmap 时: </span></span></code><code><span leaf=""><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> 统计destmap中值为</span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext">的位数 </span></span></code><code><span leaf=""><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> 只有</span><span class="code-snippet__number">1001</span><span class="code-snippet__plaintext">这个位置是</span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext"> </span></span></code><code><span leaf=""><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> 其他位置都是</span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext"> </span></span></code><code><span leaf=""><span class="code-snippet__operator">-</span><span class="code-snippet__plaintext"> 所以结果为</span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext">,表示只有一个用户完成连续打卡 </span></span></code></pre> </section> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="font-size: 16px;"><span leaf=""><br></span></span></p><ne-clipboard data="%7B%22type%22%3A%22fragment%22%2C%22name%22%3A%22%23fragment%22%2C%22children%22%3A%5B%7B%22type%22%3A%22element%22%2C%22id%22%3A%228rl96%22%2C%22name%22%3A%22h3%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ua8124606%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22bold%22%3Atrue%2C%22color%22%3A%22rgb(0%2C%200%2C%200)%22%7D%2C%22data%22%3A%22%E5%B0%8F%E7%BB%93%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22uf74cc7ae%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22ubc84b7f8%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(51%2C%2051%2C%2051)%22%2C%22fontsize%22%3A14%7D%2C%22data%22%3A%22%E6%80%9D%E8%B7%AF%E6%89%8D%E6%98%AF%E6%9C%80%E9%87%8D%E8%A6%81%EF%BC%8C%E5%BD%93%E6%88%91%E4%BB%AC%E9%81%87%E5%88%B0%E7%9A%84%E7%BB%9F%E8%AE%A1%E5%9C%BA%E6%99%AF%E5%8F%AA%E9%9C%80%E8%A6%81%E7%BB%9F%E8%AE%A1%E6%95%B0%E6%8D%AE%E7%9A%84%E4%BA%8C%E5%80%BC%E7%8A%B6%E6%80%81%EF%BC%8C%E6%AF%94%E5%A6%82%E7%94%A8%E6%88%B7%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%E3%80%81%20ip%20%E6%98%AF%E5%90%A6%E6%98%AF%E9%BB%91%E5%90%8D%E5%8D%95%E3%80%81%E4%BB%A5%E5%8F%8A%E7%AD%BE%E5%88%B0%E6%89%93%E5%8D%A1%E7%BB%9F%E8%AE%A1%E7%AD%89%E5%9C%BA%E6%99%AF%E5%B0%B1%E5%8F%AF%E4%BB%A5%E8%80%83%E8%99%91%E4%BD%BF%E7%94%A8%20Bitmap%E3%80%82%22%7D%5D%7D%2C%7B%22type%22%3A%22element%22%2C%22id%22%3A%22u18b0a1cf%22%2C%22name%22%3A%22p%22%2C%22attrs%22%3A%7B%7D%2C%22children%22%3A%5B%7B%22type%22%3A%22text%22%2C%22id%22%3A%22u7c06cd83%22%2C%22name%22%3A%22%23text%22%2C%22attrs%22%3A%7B%22color%22%3A%22rgb(51%2C%2051%2C%2051)%22%2C%22fontsize%22%3A14%7D%2C%22data%22%3A%22%E5%8F%AA%E9%9C%80%E8%A6%81%E4%B8%80%E4%B8%AA%20bit%20%E4%BD%8D%E5%B0%B1%E8%83%BD%E8%A1%A8%E7%A4%BA%200%20%E5%92%8C%201%E3%80%82%E5%9C%A8%E7%BB%9F%E8%AE%A1%E6%B5%B7%E9%87%8F%E6%95%B0%E6%8D%AE%E7%9A%84%E6%97%B6%E5%80%99%E5%B0%86%E5%A4%A7%E5%A4%A7%E5%87%8F%E5%B0%91%E5%86%85%E5%AD%98%E5%8D%A0%E7%94%A8%E3%80%82%22%7D%5D%7D%5D%2C%22attrs%22%3A%7B%7D%7D" source="https%3A%2F%2Fwww.yuque.com%2Fu12222632%2Fas5rgl%2Fypgse0xcb95ww30v"></ne-clipboard> <h3 style="font-size: 20;line-height: 28px;margin: 16px 0 5px 0;"><strong><span style="color: rgb(0, 0, 0);"><span leaf="">总结</span></span></strong></h3> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">当我们遇到的统计场景只需要统计数据的二值状态,比如用户是否存在、 ip 是否是黑名单、以及签到打卡统计等场景就可以考虑使用 Bitmap。</span></span></p> <p style="margin: 0;padding: 0;min-height: 24px;"><span style="color: rgb(51, 51, 51);font-size: 14px;"><span leaf="">只需要一个 bit 位就能表示 0 和 1。在统计海量数据的时候将大大减少内存占用。</span></span></p>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-bottom: 0px;padding-left: 10px;padding-right: 10px;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;font-family: Optima, " microsoft yahei, pingfangsc-regular, serif;font-size: 16px;color: rgb(0, 0, 0);line-height: 1.5em;word-spacing: 0em;letter-spacing: 0em;word-break: break-word;text-align: left; data-mpa-powered-by="yiban.io"> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_jpg pmzoeonjxwc5p16tqysanspnkbrxfxxfqzjf2xcbjibnwrswd6iciajlnr8lhjoqg8nhwqaido8ow6kizvibyvc0yq 640?wx_fmt="other&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 75px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none none solid;border-width: 1px 1px 2px;border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(46, 121, 80);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">引言</span><span style="display: none;"></span></h1> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">大家好,我是老三,最近在做系统设计的时候,发现要画不少时序图,以前我用的最顺手的工具是draw.io,后来也尝试了语雀自带的画图工具,感觉画画简单的图还行,但是复杂一点的,就比较吃力了。<img class="rich_pages wxw-img" data-imgfileid="100012106" data-ratio="0.6231481481481481" src="/upload/ff87ceb3bf3373e7ba337ad3765e0f47.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;">哎,这条线怎么又歪了?布局怎么又乱了?这个条怎么又对不齐了?……手忙脚乱才画好一张图,这时候我就想,有没有其它更专业的画图工具呢?大部分同事都在用Visio,辉哥给我推荐了PlantUML,说非常好用!这时候旁边来了一句—— “他就是装比!”</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-imgfileid="100012105" data-ratio="0.6866666666666666" src="/upload/1c076c802a01ffdf3089355bc706ccb4.png" data-type="gif" data-w="150" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 装比带我一个 </figcaption> </figure> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;"><span style="color: rgb(63, 63, 63);font-family: Optima, " microsoft yahei, pingfangsc-regular, serif;font-size: 16px;letter-spacing: 0.32px;text-align: left;text-wrap: wrap;> 还有这样的事?</span><span style="color: rgb(63, 63, 63);font-family: Optima, " microsoft yahei, pingfangsc-regular, serif;font-size: 16px;letter-spacing: 0.32px;text-align: left;text-wrap: wrap;>那我不能让他一个人都装了。</span></p> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">最开始看下官方文档,发现PlantUML类似MarkDown,似乎需要一点学习成本,简单用了一下,曲线还是挺平缓的,上手相当快!推荐大家也用一下试试。</p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_jpg pmzoeonjxwc5p16tqysanspnkbrxfxxfqzjf2xcbjibnwrswd6iciajlnr8lhjoqg8nhwqaido8ow6kizvibyvc0yq 640?wx_fmt="other&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 75px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none none solid;border-width: 1px 1px 2px;border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(46, 121, 80);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">一、什么是PlantUML?</span><span style="display: none;"></span></h1> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding: 10px 10px 10px 20px;border-top: 3px none rgba(0, 0, 0, 0.4);border-bottom: 3px none rgba(0, 0, 0, 0.4);border-right: 3px none rgba(0, 0, 0, 0.4);border-left-color: rgb(53, 179, 120);border-radius: 0px;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgb(251, 249, 253);width: auto;height: auto;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;overflow: auto;"> <span style="display: none;color: rgb(0, 0, 0);font-size: 16px;line-height: 1.5em;letter-spacing: 0em;"></span> <p style="text-indent: 0em;padding-top: 16px;padding-bottom: 8px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;"><strong style="color: rgb(74, 74, 74);background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(0, 0, 0, 0);width: auto;height: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;">PlantUML</strong>是一个多功能组件,可快速、直接地创建图表。用户可以使用简单直观的语言起草各种图表。</p> </blockquote> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">PlantUML是一个开源工具,它允许我们用简单的文本描述来创建UML图,包括序列图、用例图、类图、对象图、活动图、组件图、部署图、状态图,以及我们今天要讲的时序图。<img class="rich_pages wxw-img" data-imgfileid="100012104" data-ratio="0.4715909090909091" src="/upload/309b78c467ee86c76f8c221c9c90d7d7.png" data-type="png" data-w="1056" style="display: block;margin-right: auto;margin-left: auto;">除了UML图之外,PlantUML 还支持一系列其他图表,例如JSON数据、YAML数据、EBNF图表、架构图等等。PlantUML的一大优势,是图表完全用文本代码描述,这就意味着它可以作为文档嵌入到源代码中,也非常方便版本控制和多人协作,不管是迭代设计、文档编写、系统建模,PlantUML都能胜任。</p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_jpg pmzoeonjxwc5p16tqysanspnkbrxfxxfqzjf2xcbjibnwrswd6iciajlnr8lhjoqg8nhwqaido8ow6kizvibyvc0yq 640?wx_fmt="other&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 75px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none none solid;border-width: 1px 1px 2px;border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(46, 121, 80);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">二、快速入门</span><span style="display: none;"></span></h1> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_png pmzoeonjxwc5p16tqysanspnkbrxfxxfh0iaicjh4eraszazhu0qdcliaibiaib5o7rqxib2tnmlej1x74xjyyonrdk9a 640?wx_fmt="png&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">PlantUML插件</span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">为了便捷地使用PlantUML,许多流行的IDE和代码编辑器提供了集成PlantUML的插件,如Visual Studio Code、IntelliJ IDEA、Eclipse等。插件提供了实时预览、语法高亮和图表导出等功能,能帮助我们更快捷,更高效地画图,整体上IDEA的插件用起来体验最好,但是IDEA大家懂的,太占内存了,VS Code相对而言,用起来就会轻量很多。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> <p style="line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">IntelliJ IDEA:比如 "PlantUML integration" 可以让我们直接在 IDE 中查看和编辑 PlantUML 图表</p> <figure 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-imgfileid="100012107" data-ratio="0.737037037037037" src="/upload/f67cb608f92c4530eaf5d8c179c4cb7b.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> PlantUML integration </figcaption> </figure> </section></li> <ul style="list-style-type: square;margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 插件使用效果 </section></li> </ul> </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-imgfileid="100012108" data-ratio="0.46111111111111114" src="/upload/3d9f16dac8931a7db574014f7633f677.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> image.png </figcaption> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> VS Code:https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml </section></li> <ul style="list-style-type: square;margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 插件市场: </section></li> </ul> </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-imgfileid="100012112" data-ratio="0.6981481481481482" src="/upload/3f000d36c8b05d5e9f4591c8a8561329.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> image.png </figcaption> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 插件使用效果: </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-imgfileid="100012113" data-ratio="0.5537037037037037" src="/upload/2dac24f33630e93aa83ff4ac2e0121de.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> image.png </figcaption> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_png pmzoeonjxwc5p16tqysanspnkbrxfxxfh0iaicjh4eraszazhu0qdcliaibiaib5o7rqxib2tnmlej1x74xjyyonrdk9a 640?wx_fmt="png&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">Hello World!</span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">我们先来看个最简单的例子,通过<code style="color: rgb(40, 202, 113);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(27, 31, 35, 0.05);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: " operator mono, consolas, monaco, menlo, monospace;word-break: break-all;>-></code> 、<code style="color: rgb(40, 202, 113);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(27, 31, 35, 0.05);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: " operator mono, consolas, monaco, menlo, monospace;word-break: break-all;>--></code>和<code style="color: rgb(40, 202, 113);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(27, 31, 35, 0.05);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: " operator mono, consolas, monaco, menlo, monospace;word-break: break-all;> :</code>就可以在参与者之间传递消息,不用明确声明参与者。</p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;">@startuml</span><br>老张 -> 老王 : 老王,你好啊<br>老王--> 老张: 老张,你好啊<br><br>老张 -> 老王: 最近有空一起喝茶<br>老张 <-- 老王: OK<br><span style="color: #61aeee;line-height: 26px;">@enduml</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-imgfileid="100012109" data-ratio="1.2377777777777779" src="/upload/7031b84b4b941faf897916f4384d5b98.png" data-type="png" data-w="450" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> hello </figcaption> </figure> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_jpg pmzoeonjxwc5p16tqysanspnkbrxfxxfqzjf2xcbjibnwrswd6iciajlnr8lhjoqg8nhwqaido8ow6kizvibyvc0yq 640?wx_fmt="other&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 75px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none none solid;border-width: 1px 1px 2px;border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(46, 121, 80);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">三、PlantUML时序图语法</span><span style="display: none;"></span></h1> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">接下来,我们看看PlantUML时序图的一些具体语法。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_png pmzoeonjxwc5p16tqysanspnkbrxfxxfh0iaicjh4eraszazhu0qdcliaibiaib5o7rqxib2tnmlej1x74xjyyonrdk9a 640?wx_fmt="png&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">声明参与者</span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">我们使用关键字participant 来声明参与者,就可以对该参与者进行更多的控制。声明的顺序就是默认的<strong style="color: rgb(74, 74, 74);background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;">显示顺序</strong>。我们也可以用这些关键字来声明参与者,给参与者设置不同的形状。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> actor(角色) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> boundary(边界) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> control(控制) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> entity(实体) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> database(数据库) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> collections(集合) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> queue(队列) </section></li> </ul> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">我们还可以通过 <code style="color: rgb(40, 202, 113);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(27, 31, 35, 0.05);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: " operator mono, consolas, monaco, menlo, monospace;word-break: break-all;>as</code>关键字重命名参与者。</p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;">@startuml</span><br>participant Participant as Foo<br>actor Actor as Foo1<br>boundary Boundary as Foo2<br>control Control as Foo3<br>entity Entity as Foo4<br>database Database as Foo5<br>collections Collections as Foo6<br>queue Queue as Foo7<br><span style="color: #61aeee;line-height: 26px;">@enduml</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-imgfileid="100012110" data-ratio="0.3225419664268585" src="/upload/297e0600ba7b1b74df24823626fc935d.png" data-type="png" data-w="834" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 参与者 </figcaption> </figure> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">默认的颜色比较单调,也可以通过<code style="color: rgb(40, 202, 113);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(27, 31, 35, 0.05);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: " operator mono, consolas, monaco, menlo, monospace;word-break: break-all;>#</code>来设置参与者的颜色:</p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;">@startuml</span><br>actor Bob #blue<br><span style="color: #98c379;line-height: 26px;">' The only difference between actor<br>'</span>and participant is the drawing<br>participant Alice #SkyBlue<br>participant <span style="color: #98c379;line-height: 26px;">"I have a really\nlong name"</span> as L #<span style="color: #d19a66;line-height: 26px;">00f</span>f00<br><br>Alice->Bob: Authentication Request<br>Bob->Alice: Authentication Response<br>Bob->L: Log transaction<br><span style="color: #61aeee;line-height: 26px;">@enduml</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-imgfileid="100012111" data-ratio="0.8607038123167156" src="/upload/cb3fe7d790dda89c1766c13868b3659d.png" data-type="png" data-w="682" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 上颜色的参与者 </figcaption> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_png pmzoeonjxwc5p16tqysanspnkbrxfxxfh0iaicjh4eraszazhu0qdcliaibiaib5o7rqxib2tnmlej1x74xjyyonrdk9a 640?wx_fmt="png&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">消息传递</span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">在不同参与者之间,通过箭头+:来表示消息传递。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 同步消息: </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;">A -> B: 同步消息文本<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-imgfileid="100012115" data-ratio="0.9397163120567376" src="/upload/f25483af4ba1f4673aa1771832b96c0f.png" data-type="png" data-w="282" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 同步消息 </figcaption> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 异步消息:由发送者A指向接收者B,表示A发送后不需要等待B立即处理。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;">A ->> B: 异步消息文本<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-imgfileid="100012118" data-ratio="0.9408284023668639" src="/upload/a3b74cf0c49f24f66935f368cddf1bc3.png" data-type="png" data-w="338" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 异步消息 </figcaption> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 返回消息:通常从接收者返回到发送者,标识一个回应。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;">A <-- B: 返回消息文本<br><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-imgfileid="100012114" data-ratio="0.9408284023668639" src="/upload/fdacd8718cd74973b92c5d215b6eb540.png" data-type="png" data-w="338" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 返回消息 </figcaption> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> <p style="line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">自调用:一个参与者直接发送消息给自己,表示自我处理或运算。</p> <pre style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;color: rgb(171, 178, 191);width: auto;margin-left: 2px;margin-right: 2px;padding: 15px 4px 2px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);word-break: break-all;background: rgb(40, 44, 52);display: -webkit-box;font-family: " operator mono, consolas, monaco, menlo, monospace;border-radius: 0px;font-size: 12px;>A ->A: 自调用<br></code></pre> <figure 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-imgfileid="100012117" data-ratio="2.0406976744186047" src="/upload/b139dc43cef7646d7004c800b1a840ef.png" data-type="png" data-w="172" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 自调用 </figcaption> </figure> </section></li> </ul> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_png pmzoeonjxwc5p16tqysanspnkbrxfxxfh0iaicjh4eraszazhu0qdcliaibiaib5o7rqxib2tnmlej1x74xjyyonrdk9a 640?wx_fmt="png&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">生命线(Lifeline)与激活条(Activation Bar)</span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">在时序图中,生命线表示对象在一段时间内的活动状态,也就是从参与者往下延伸的那条虚线。激活条用来表示参与者或对象在处理某个任务期间的活动状态,是生命线的一部分,矩形条形式出现。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 生命线的激活与撤销:可以用下面这些关键字来控制生命线的激活与撤销 </section></li> <ul style="list-style-type: square;margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> activate: 显示参与者的活动状态开始 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> deactivate: 指示参与者的活动状态结束。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> destroy: 用于表示参与者的生命线终结,通常表示对象生命周期的结束。 </section></li> </ul> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;">@startuml</span><br>participant User<br>User -> A: DoWork<br>activate A<br>A -> B: << createRequest >><br>activate B<br>B -> C: DoWork<br>activate C<br>C --> B: WorkDone<br>destroy C<br>B --> A: RequestCreated<br>deactivate B<br>A -> User: Done<br>deactivate A<br><span style="color: #61aeee;line-height: 26px;">@enduml</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-imgfileid="100012116" data-ratio="0.8515463917525773" src="/upload/c74387e681d903d2ff2526c17fae0bf2.png" data-type="png" data-w="485" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 生命线的激活与撤销 </figcaption> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 生命线的嵌套与颜色:我们还可以使用嵌套激活条来表示内部调用,并可以给生命线添加颜色。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;">@startuml</span><br>participant User<br>User -> A: DoWork<br>activate A #FFBBBB<br>A -> A: Internal call<br>activate A #DarkSalmon<br>A -> B: << createRequest >><br>activate B<br>B --> A: RequestCreated<br>deactivate B<br>deactivate A<br>A -> User: Done<br>deactivate A<br><span style="color: #61aeee;line-height: 26px;">@enduml</span><br><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-imgfileid="100012122" data-ratio="1.088992974238876" src="/upload/604e66046aba4639d92f0cc693dd97db.png" data-type="png" data-w="427" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 生命线的嵌套与颜色 </figcaption> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 自动激活:在发送消息时自动显示激活条。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;">A->B++: 激活B并发送消息<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-imgfileid="100012120" data-ratio="0.8079268292682927" src="/upload/9e795f7d95d6d47f5785343fe21e8395.png" data-type="png" data-w="328" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 自动激活 </figcaption> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 自动去激活:在接收回应时自动隐藏激活条。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;">A->B++: 激活B并发送消息<br>A <--B--: B去激活并回应消息<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-imgfileid="100012124" data-ratio="0.9095890410958904" src="/upload/9f4defcf1a483d61662ea4eb3c146357.png" data-type="png" data-w="365" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 自动去激活 </figcaption> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_png pmzoeonjxwc5p16tqysanspnkbrxfxxfh0iaicjh4eraszazhu0qdcliaibiaib5o7rqxib2tnmlej1x74xjyyonrdk9a 640?wx_fmt="png&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">分组和替代</span><span style="display: none;"></span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 分组:用于逻辑上分组一系列交互。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;">group 分组名<br>A -> B: 消息<br>...<br>end group<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-imgfileid="100012121" data-ratio="1.7433628318584071" src="/upload/e7100f2cfd0d21132a6aa6d7b66cec7e.png" data-type="png" data-w="226" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 分组 </figcaption> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 替代(Alt/Else):表示基于条件的替代执行流程。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;">alt 条件<span style="color: #d19a66;line-height: 26px;">1</span><br>A -> B: 满足条件<span style="color: #d19a66;line-height: 26px;">1</span>的消息<br><span style="color: #c678dd;line-height: 26px;">else</span> 条件<span style="color: #d19a66;line-height: 26px;">2</span><br>A -> B: 满足条件<span style="color: #d19a66;line-height: 26px;">2</span>的消息<br>end<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-imgfileid="100012123" data-ratio="1.1624203821656052" src="/upload/5fca183fc5a2d4f0e86c24b6c9434b45.png" data-type="png" data-w="314" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 替代 </figcaption> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_png pmzoeonjxwc5p16tqysanspnkbrxfxxfh0iaicjh4eraszazhu0qdcliaibiaib5o7rqxib2tnmlej1x74xjyyonrdk9a 640?wx_fmt="png&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">注释</span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">注释用于添加说明性文本。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 可以用note left of,note right of或note over来控制注释相对节点的位置,还可以通过修改背景色来高亮显示注释。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;">@startuml</span><br>participant Alice<br>participant Bob<br>note left of Alice #aqua<br>This is displayed<br>left of Alice.<br>end note<br><br>note right of Alice: This is displayed right of Alice.<br><br>note over Alice: This is displayed over Alice.<br><br>note over Alice, Bob #FFAAAA: This is displayed\n over Bob and Alice.<br><br>note over Bob, Alice<br>This is yet another<br>example of<br>a <span style="color: #c678dd;line-height: 26px;">long</span> note.<br>end note<br><span style="color: #61aeee;line-height: 26px;">@enduml</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-imgfileid="100012128" data-ratio="1.055441478439425" src="/upload/85fa9596bc9fe5d3ade903f06596066a.png" data-type="png" data-w="487" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 注释 </figcaption> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_png pmzoeonjxwc5p16tqysanspnkbrxfxxfh0iaicjh4eraszazhu0qdcliaibiaib5o7rqxib2tnmlej1x74xjyyonrdk9a 640?wx_fmt="png&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">颜色</span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">Choosing colors在 PlantUML 中,我们可以对时序图的各个元素自定义颜色,比如参与者(actors)、对象(objects)、激活条(activation bars)等,来让我们的时序图更加美观。在声明元素时,可以直接指定颜色,格式为#颜色代码。颜色代码可以是不同的形式:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 直接指定颜色:颜色代码可以是一个十六进制颜色值,也可以是预定义的颜色名称。 </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;">@startuml</span><br>actor 用户 #Green<br>participant 参与者 #B4A7E5<br><br>用户-[#red]>参与者:消息<br>activate 参与者 #Blue<br><br><span style="color: #61aeee;line-height: 26px;">@enduml</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-imgfileid="100012125" data-ratio="1.9739130434782608" src="/upload/44f17b8e66ed9c747c0815e9dc0c7e64.png" data-type="png" data-w="230" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 直接指定颜色 </figcaption> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 使用 <code style="background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(27, 31, 35, 0.05);width: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: " operator mono, consolas, monaco, menlo, monospace;word-break: break-all;>skinparam</code> 设置颜色:除了直接为特定元素指定颜色外,还可以使用 <code style="background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(27, 31, 35, 0.05);width: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: " operator mono, consolas, monaco, menlo, monospace;word-break: break-all;>skinparam</code> 全局设置时序图中的颜色。用这种方式更改元素的默认颜色比较方便: </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;">@startuml</span><br>skinparam ActorBorderColor #DarkOrange<br>skinparam ParticipantBackgroundColor #SkyBlue<br><br>actor 用户<br>participant 参与者<br><span style="color: #61aeee;line-height: 26px;">@enduml</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-imgfileid="100012127" data-ratio="1.6869565217391305" src="/upload/05d2d28b9266bdc76217160a91f84a2b.png" data-type="png" data-w="230" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 使用 <code>skinparam</code> 设置颜色 </figcaption> </figure> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">当使用 <code style="color: rgb(40, 202, 113);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(27, 31, 35, 0.05);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: " operator mono, consolas, monaco, menlo, monospace;word-break: break-all;>skinparam</code> 时,我们可以设置许多不同属性的颜色,如边框颜色(BorderColor)、背景颜色(BackgroundColor)、字体颜色(FontColor)和激活条颜色(SequenceGroupBodyBackgroundColor)。更多语法可以直接查看官方文档:顺序图的语法和功能,目前这些内容,已经足够我们常见的时序图需求了。</p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_jpg pmzoeonjxwc5p16tqysanspnkbrxfxxfqzjf2xcbjibnwrswd6iciajlnr8lhjoqg8nhwqaido8ow6kizvibyvc0yq 640?wx_fmt="other&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 75px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none none solid;border-width: 1px 1px 2px;border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(46, 121, 80);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">四、完整实例</span><span style="display: none;"></span></h1> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">我们接下来看一个稍微完整一点的例子,在这个例子中,我们的需求,是要在原本的登录的基础上,引入Google登录。</p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;margin-top: 10px;margin-bottom: 10px;"><span style="display: block;background: url(" https: mmbiz.qpic.cn mmbiz_svg iahdqiccc5vbskyvchl3yzerhnm8cv0eribia6kxszvzrfthxrcn46sxzylwhefibb5fp8bicgummdghws2e8cur8qzy02zdldnaria 640?wx_fmt="svg&from=appmsg")" 10px 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;">@startuml</span><br>skinparam ParticipantBackgroundColor #DeepSkyBlue<br><br>actor 用户 as c #DeepSkyBlue<br>participant <span style="color: #98c379;line-height: 26px;">"客户端"</span> as client<br>participant <span style="color: #98c379;line-height: 26px;">"服务网关"</span> as ga<br>participant <span style="color: #98c379;line-height: 26px;">"用户服务"</span> as user<br>database <span style="color: #98c379;line-height: 26px;">"数据库"</span> as DB #DeepSkyBlue<br>participant <span style="color: #98c379;line-height: 26px;">"Google服务"</span> as google #LightCoral<br><br>activate c #DeepSkyBlue<br>activate client #DeepSkyBlue<br><br>c->client:用户登录<br><br>group#LightCoral #LightCoral Google登录客户端流程<br> client -> google : 请求Google OAuth登录<br> activate google #DeepSkyBlue<br> google-->client:登录url<br> client->google:跳转登录页<br> google -> google : 用户登录<br> google --> client : Google登录Token<br> deactivate google<br>end<br><br>|||<br><br>client -> ga : 登录请求<br>note right#LightCoral:新增登录方式,三方登录请求实体<br>activate ga #DeepSkyBlue<br>ga ->user:请求转发<br>activate user #DeepSkyBlue<br><br><br>alt#DeepSkyBlue 常规登录<br> user -> DB : 查询用户信息<br> activate DB #DeepSkyBlue<br> DB -> user : 用户信息<br> deactivate DB<br> user->user:登录密码校验<br><br>|||<br><span style="color: #c678dd;line-height: 26px;">else</span> Google登录<br> group#LightCoral #LightCoral Google登录服务端流程<br> user->google:验证token<br> activate google #DeepSkyBlue<br> google-->user:用户信息<br> deactivate google<br> user->user:存储或更新用户信息<br> end group<br>end<br><br><br>user-->ga:登录结果<br>deactivate user<br>ga -> client : 响应<br>deactivate ga<br>alt#DeepSkyBlue 成功<br> client -> c : 登录成功<br><span style="color: #c678dd;line-height: 26px;">else</span> 失败<br> client -> c : 登录失败<br>end<br>deactivate client<br>|||<br><span style="color: #61aeee;line-height: 26px;">@enduml</span><br><br><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-imgfileid="100012129" data-ratio="1.7737512242899118" src="/upload/d35a0f3d54b426c0500f40eb0cf93576.png" data-type="png" data-w="1021" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> <figcaption style="color: rgb(136, 136, 136);font-size: 12px;line-height: 1.5em;letter-spacing: 0em;text-align: center;margin-top: 5px;"> 登录时序图 </figcaption> </figure> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;background-attachment: scroll;background-clip: border-box;background-image: url(" https: mmbiz.qpic.cn mmbiz_jpg pmzoeonjxwc5p16tqysanspnkbrxfxxfqzjf2xcbjibnwrswd6iciajlnr8lhjoqg8nhwqaido8ow6kizvibyvc0yq 640?wx_fmt="other&from=appmsg");background-origin:" padding-box;background-position: 50% 50%;background-repeat: no-repeat;background-size: 75px;width: auto;height: auto;align-items: unset;border-style: none;border-width: 1px;border-color: rgb(0, 0, 0);border-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow: unset;text-shadow: none;transform: none;-webkit-box-reflect: unset;><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-style: none none solid;border-width: 1px 1px 2px;border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(46, 121, 80);border-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;overflow: unset;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;">五、总结</span><span style="display: none;"></span></h1> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">PlantUML使用起来整体上还是非常舒服的,对我而言,这几个特点让我爱不释手:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 提供了类似MarkDown的所见即所得的使用体验,免去调整图形之扰 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> PlantUML本质是文本,可以进行版本控制,多人协同 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> 语雀支持文本画图的功能,可以嵌入PlantUML文本,支持在语雀文档里直接修改 </section></li> </ul> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;">PlantUML还有很强大的扩展性和灵活性,我们可以通过 官方文档:<span style="color: rgb(91, 128, 141);font-family: Vollkorn, Palatino, Times;letter-spacing: normal;orphans: 4;text-align: start;white-space: pre-wrap;word-spacing: 0.85px;background-color: rgb(255, 255, 255);text-decoration: underline;">https://plantuml.com/zh/</span> 继续探索更多高级语法和技巧,来绘制更加复杂和丰富的图表。</p> <hr data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-style: none;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 0px;background: linear-gradient(90deg, rgba(93, 186, 133, 0) 0%, rgba(93, 186, 133, 0.75) 50%, rgba(93, 186, 133, 0) 100%) 0% 0% / auto no-repeat scroll padding-box border-box rgba(255, 255, 255, 0);width: auto;height: 2px;"> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;text-indent: 0em;padding-top: 16px;padding-bottom: 8px;"><strong style="color: rgb(74, 74, 74);background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;">参考:</strong></p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li style="font-size: 10px;"> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> <span style="font-size: 10px;">开源工具,使用简单的文字描述画UML图</span> </section></li> <li style="font-size: 10px;"> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> <span style="font-size: 10px;">Choosing colors</span> </section></li> <li style="font-size: 10px;"> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> <span style="font-size: 10px;">顺序图的语法和功能</span> </section></li> <li style="font-size: 10px;"> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> <span style="font-size: 10px;">如何使用 PlantUML 画系统设计图?- 掘金</span> </section></li> <li style="font-size: 10px;"> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> <span style="font-size: 10px;">顺序图的语法和功能</span> </section></li> <li style="font-size: 10px;"> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);line-height: 1.8em;letter-spacing: 0.02em;"> <span style="font-size: 10px;">GPT老师</span> </section></li> </ol> </section>
作者:微信小助手
<p style="margin-bottom: 0px;letter-spacing: 0.578px;text-wrap: wrap;text-align: center;"><span leaf=""><img class="rich_pages wxw-img" data-imgfileid="100015609" data-ratio="0.5714285714285714" data-s="300,640" src="/upload/5e98b50f0a7c61f3ccf1310a77e91fa9.png" data-type="png" data-w="1792" style="height: 330px;width: 578px;"></span></p> <section style="margin-bottom: 0px;letter-spacing: 0.578px;text-wrap: wrap;line-height: 2em;"> <span style="letter-spacing: 0.578px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: var(--articlefontsize);><span leaf=""><br></span></span> </section> <p data-sourcepos="1:1-1:75" style="box-sizing: border-box;margin-top: 0px !important;margin-bottom: 1rem;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><strong style="box-sizing: border-box;font-weight: 600;color: rgb(51, 51, 51);"><span leaf="">SpringBoot 实现 License 认证:快速校验有效期的简洁方案</span></strong></p> <p data-sourcepos="3:1-3:789" style="box-sizing: border-box;margin-top: 0px;margin-bottom: 1rem;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span leaf="">在现代软件开发中,特别是商业软件领域,</span><strong style="box-sizing: border-box;font-weight: 600;color: rgb(51, 51, 51);"><span leaf="">License认证</span></strong><span leaf="">是一种至关重要的技术,用于限制软件的使用范围和授权模式。它不仅保护开发者的利益,也为用户提供合法使用的依据。License认证通常涉及生成密钥对、签发证书以及验证有效性等步骤,这些过程虽然复杂,但通过适当的工具和技术可以简化实现。在本篇文章中,我们将基于</span><span leaf=""> </span><strong style="box-sizing: border-box;font-weight: 600;color: rgb(51, 51, 51);"><span leaf="">SpringBoot</span></strong><span leaf=""> </span><span leaf="">框架,结合</span><span leaf=""> </span><strong style="box-sizing: border-box;font-weight: 600;color: rgb(51, 51, 51);"><span leaf="">TrueLicense</span></strong><span leaf=""> </span><span leaf="">开源工具,展示如何快速实现 License 认证,尤其是围绕“有效期校验”的核心功能。通过阅读本文,您将掌握如何生成密钥对、创建 License 证书以及如何在项目中集成并校验证书的有效性,助力您构建更加安全可靠的软件系统。</span></p> <h3 data-sourcepos="5:1-5:18" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 1.25rem;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">License 简介</span></h3> <p data-sourcepos="7:1-7:104" style="box-sizing: border-box;margin-top: 0px;margin-bottom: 1rem;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span leaf="">License 即版权许可证书,用于为收费软件提供访问许可证明,常见于以下场景:</span></p> <ul style="box-sizing: border-box;padding-left: 2rem;margin-top: 0px;margin-bottom: 1rem;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none; class="list-paddingleft-1"> <li style="box-sizing: border-box;"><strong style="box-sizing: border-box;font-weight: 600;color: rgb(51, 51, 51);"><span leaf="">应用场景</span></strong> <section> <span leaf=""><br></span> <section> <span leaf="">部署在客户内网环境,开发者无法控制其网络状态,需通过离线方式校验证书有效性。</span> </section> </section></li> <li style="box-sizing: border-box;margin-top: 0.25rem;"><strong style="box-sizing: border-box;font-weight: 600;color: rgb(51, 51, 51);"><span leaf="">授权原理</span></strong> <section> <span leaf=""><br></span> <section> <span leaf="">利用证书管理工具生成密钥对,私钥用于创建 License 证书,公钥验证其合法性和有效期。</span> </section> </section></li> </ul> <h3 data-sourcepos="14:1-14:28" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 1.25rem;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">授权者生成密钥对</span></h3> <p data-sourcepos="16:1-16:86" style="box-sizing: border-box;margin-top: 0px;margin-bottom: 1rem;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span leaf="">授权者通过</span><span leaf=""> </span><code style="box-sizing: border-box;font-family: SFMono-Regular, Consolas, " liberation mono, menlo, monospace;font-size: 13.6px;padding: 0.2rem 0.4rem;margin: 0px;background-color: rgb(247, 248, 248);color: rgb(9, 132, 79);border-radius: 0.1875rem;><span leaf="">Keytool</span></code><span leaf=""> </span><span leaf="">工具生成私钥和公钥,并完成证书库的管理。</span></p> <pre data-sourcepos="18:1-28:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(142, 156, 146);"><span leaf=""># 生成私钥库</span></span><span leaf=""><br></span><span leaf="">keytool </span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-genkeypair</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-keysize</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">2048</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-validity</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">3650</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-alias</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"privateKey"</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-keystore</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"privateKeys.keystore"</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-storepass</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"myStorePass123"</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-keypass</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"myKeyPass123"</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-dname</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN"</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(142, 156, 146);"><span leaf=""># 导出公钥到文件</span></span><span leaf=""><br></span><span leaf="">keytool </span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-exportcert</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-alias</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"privateKey"</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-keystore</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"privateKeys.keystore"</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-storepass</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"myStorePass123"</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-file</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"certfile.cer"</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(142, 156, 146);"><span leaf=""># 导入证书到公钥库</span></span><span leaf=""><br></span><span leaf="">keytool </span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-import</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-alias</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"publicCert"</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-file</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"certfile.cer"</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-keystore</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"publicCerts.keystore"</span></span><span style="box-sizing: border-box;color: rgb(120, 72, 48);"><span leaf="">-storepass</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"myStorePass123"</span></span><span leaf=""><br></span><span leaf=""><br></span></code></pre> <h3 data-sourcepos="30:1-30:34" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 1.25rem;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">授权者生成 License 文件</span></h3> <h4 data-sourcepos="32:1-32:17" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 16px;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">Maven 依赖</span></h4> <p data-sourcepos="34:1-34:74" style="box-sizing: border-box;margin-top: 0px;margin-bottom: 1rem;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span leaf="">在项目的</span><span leaf=""> </span><code style="box-sizing: border-box;font-family: SFMono-Regular, Consolas, " liberation mono, menlo, monospace;font-size: 13.6px;padding: 0.2rem 0.4rem;margin: 0px;background-color: rgb(247, 248, 248);color: rgb(9, 132, 79);border-radius: 0.1875rem;><span leaf="">pom.xml</span></code><span leaf=""> </span><span leaf="">文件中添加</span><span leaf=""> </span><code style="box-sizing: border-box;font-family: SFMono-Regular, Consolas, " liberation mono, menlo, monospace;font-size: 13.6px;padding: 0.2rem 0.4rem;margin: 0px;background-color: rgb(247, 248, 248);color: rgb(9, 132, 79);border-radius: 0.1875rem;><span leaf="">TrueLicense</span></code><span leaf=""> </span><span leaf="">的核心库依赖:</span></p> <pre data-sourcepos="36:1-42:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><</span></span><span leaf="">dependency</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><</span></span><span leaf="">groupId</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf="">de.schlichtherle.truelicense</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><!--/</span--></span><span leaf="">groupId</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><</span></span><span leaf="">artifactId</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf="">truelicense-core</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><!--/</span--></span><span leaf="">artifactId</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><</span></span><span leaf="">version</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf="">1.33</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><!--/</span--></span><span leaf="">version</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><!--/</span--></span><span leaf="">dependency</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf=""><br></span></span></span></span></span></code></pre> <p data-sourcepos="44:1-44:17" style="box-sizing: border-box;margin-top: 0px;margin-bottom: 1rem;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span leaf="">License 生成类</span></p> <p data-sourcepos="46:1-46:56" style="box-sizing: border-box;margin-top: 0px;margin-bottom: 1rem;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span leaf="">以下代码实现了</span><span leaf=""> </span><code style="box-sizing: border-box;font-family: SFMono-Regular, Consolas, " liberation mono, menlo, monospace;font-size: 13.6px;padding: 0.2rem 0.4rem;margin: 0px;background-color: rgb(247, 248, 248);color: rgb(9, 132, 79);border-radius: 0.1875rem;><span leaf="">License</span></code><span leaf=""> </span><span leaf="">文件的生成逻辑。</span></p> <pre data-sourcepos="48:1-124:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">package</span></span><span leaf=""> </span><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">com</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">icoderoad</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">de</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">schlichtherle</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;"><span leaf="">*</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">lombok</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">extern</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">slf4j</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Slf4j</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">javax</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">security</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">auth</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">x500</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">X500Principal</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">io</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">File</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">util</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Date</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">util</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">prefs</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Preferences</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Slf4j</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCreator</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">static</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">final</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">X500Principal</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">DEFAULT_HOLDER_AND_ISSUER</span></span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">X500Principal</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">static</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">void</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">main</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">[</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">]</span></span><span leaf=""> args</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCreatorParam</span></span><span leaf=""> param </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCreatorParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setSubject</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"license"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setPrivateAlias</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"privateKey"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setKeyPass</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"myKeyPass123"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setStorePass</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"myStorePass123"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setLicensePath</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"license.lic"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setPrivateKeysStorePath</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"privateKeys.keystore"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setIssuedTime</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Date</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setExpiryTime</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Date</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">System</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">currentTimeMillis</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;"><span leaf="">+</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">10L</span></span><span style="box-sizing: border-box;"><span leaf="">*</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">365</span></span><span style="box-sizing: border-box;"><span leaf="">*</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">24</span></span><span style="box-sizing: border-box;"><span leaf="">*</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">60</span></span><span style="box-sizing: border-box;"><span leaf="">*</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">60</span></span><span style="box-sizing: border-box;"><span leaf="">*</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">1000</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setConsumerType</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"user"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setConsumerAmount</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">1</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setDescription</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"This is a license file."</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">try</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCreator</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">generateLicense</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> log</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">info</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"License file generated successfully at: {}"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getLicensePath</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">catch</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Exception</span></span><span leaf=""> e</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> log</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">error</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"Failed to generate license file"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> e</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">void</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">generateLicense</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCreatorParam</span></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">try</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseManager</span></span><span leaf=""> licenseManager </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseManager</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">initLicenseParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseContent</span></span><span leaf=""> licenseContent </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">initLicenseContent</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> licenseManager</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">store</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">licenseContent</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">File</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getLicensePath</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">catch</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Exception</span></span><span leaf=""> e</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> log</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">error</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"License generation failed"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> e</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">static</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseParam</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">initLicenseParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCreatorParam</span></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Preferences</span></span><span leaf=""> preferences </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Preferences</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">userNodeForPackage</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCreator</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">CipherParam</span></span><span leaf=""> cipherParam </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">DefaultCipherParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getStorePass</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">KeyStoreParam</span></span><span leaf=""> privateStoreParam </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">CustomKeyStoreParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCreator</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getPrivateKeysStorePath</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getPrivateAlias</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getStorePass</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getKeyPass</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">DefaultLicenseParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getSubject</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> preferences</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> privateStoreParam</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> cipherParam</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">static</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseContent</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">initLicenseContent</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCreatorParam</span></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseContent</span></span><span leaf=""> content </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseContent</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> content</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setHolder</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">DEFAULT_HOLDER_AND_ISSUER</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> content</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setIssuer</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">DEFAULT_HOLDER_AND_ISSUER</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> content</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setSubject</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getSubject</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> content</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setIssued</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getIssuedTime</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> content</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setNotBefore</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getIssuedTime</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> content</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setNotAfter</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getExpiryTime</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> content</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setConsumerType</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getConsumerType</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> content</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setConsumerAmount</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getConsumerAmount</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> content</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setInfo</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getDescription</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span leaf=""> content</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span></code></pre> <h4 data-sourcepos="126:1-126:28" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 16px;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">LicenseCreatorParam 类</span></h4> <pre data-sourcepos="128:1-152:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">package</span></span><span leaf=""> </span><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">com</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">icoderoad</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">com</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">fasterxml</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">jackson</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">annotation</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">JsonFormat</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">lombok</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Data</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">util</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Date</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Data</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCreatorParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> subject</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> privateAlias</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> keyPass</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> storePass</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> licensePath</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> privateKeysStorePath</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@JsonFormat</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">pattern </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"yyyy-MM-dd HH:mm:ss"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> timezone </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"GMT+8"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Date</span></span><span leaf=""> issuedTime</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@JsonFormat</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">pattern </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"yyyy-MM-dd HH:mm:ss"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> timezone </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"GMT+8"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Date</span></span><span leaf=""> expiryTime</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> consumerType</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Integer</span></span><span leaf=""> consumerAmount</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> description</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span></code></pre> <h4 data-sourcepos="154:1-154:28" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 16px;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">CustomKeyStoreParam 类</span></h4> <pre data-sourcepos="156:1-191:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">package</span></span><span leaf=""> </span><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">com</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">icoderoad</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">de</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">schlichtherle</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">AbstractKeyStoreParam</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">CustomKeyStoreParam</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">extends</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">AbstractKeyStoreParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">final</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> storePath</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">final</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> alias</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">final</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> storePwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">final</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> keyPwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">CustomKeyStoreParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Class</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><</span></span><span style="box-sizing: border-box;"><span leaf="">?</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf=""> clazz</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> storePath</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> alias</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> storePwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> keyPwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">super</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">clazz</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> storePath</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">this</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">storePath </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span leaf=""> storePath</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">this</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">alias </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span leaf=""> alias</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">this</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">storePwd </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span leaf=""> storePwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">this</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">keyPwd </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span leaf=""> keyPwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getAlias</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span leaf=""> alias</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getStorePwd</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span leaf=""> storePwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getKeyPwd</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span leaf=""> keyPwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span></code></pre> <h3 data-sourcepos="193:1-193:25" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 1.25rem;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">使用者配置验证</span></h3> <p data-sourcepos="195:1-195:116" style="box-sizing: border-box;margin-top: 0px;margin-bottom: 1rem;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span leaf="">使用者需在项目中加载</span><span leaf=""> </span><code style="box-sizing: border-box;font-family: SFMono-Regular, Consolas, " liberation mono, menlo, monospace;font-size: 13.6px;padding: 0.2rem 0.4rem;margin: 0px;background-color: rgb(247, 248, 248);color: rgb(9, 132, 79);border-radius: 0.1875rem;><span leaf="">publicKeys.keystore</span></code><span leaf=""> </span><span leaf="">和</span><span leaf=""> </span><code style="box-sizing: border-box;font-family: SFMono-Regular, Consolas, " liberation mono, menlo, monospace;font-size: 13.6px;padding: 0.2rem 0.4rem;margin: 0px;background-color: rgb(247, 248, 248);color: rgb(9, 132, 79);border-radius: 0.1875rem;><span leaf="">license.lic</span></code><span leaf=""> </span><span leaf="">文件,并在应用启动时进行校验。</span></p> <ul style="box-sizing: border-box;padding-left: 2rem;margin-top: 0px;margin-bottom: 1rem;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none; class="list-paddingleft-1"> <li style="box-sizing: border-box;"><strong style="box-sizing: border-box;font-weight: 600;color: rgb(51, 51, 51);"><span leaf="">校验逻辑</span></strong> <section> <span leaf="">:通过公钥验证证书的合法性及有效期。</span> </section></li> <li style="box-sizing: border-box;margin-top: 0.25rem;"><strong style="box-sizing: border-box;font-weight: 600;color: rgb(51, 51, 51);"><span leaf="">安全建议</span></strong> <section> <span leaf="">:妥善保护私钥文件,不得泄露给使用者。</span> </section></li> </ul> <h3 data-sourcepos="200:1-200:56" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 1.25rem;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">基于 TrueLicense 的 License 验证与安装优化</span></h3> <p data-sourcepos="202:1-202:169" style="box-sizing: border-box;margin-top: 0px;margin-bottom: 1rem;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span leaf="">本文将详细介绍如何在项目中通过 TrueLicense 实现 License 的验证与安装。以下优化后的代码和配置旨在满足不同使用场景的需求。</span></p> <h4 data-sourcepos="204:1-204:34" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 16px;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">使用者的</span><span leaf=""> </span><code style="box-sizing: border-box;font-family: SFMono-Regular, Consolas, " liberation mono, menlo, monospace;font-size: 13.6px;padding: 0.2rem 0.4rem;margin: 0px;background-color: rgb(247, 248, 248);color: rgb(9, 132, 79);border-radius: 0.1875rem;><span leaf="">pom.xml</span></code><span leaf=""> </span><span leaf="">配置</span></h4> <pre data-sourcepos="205:1-212:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(142, 156, 146);"><span leaf=""><!-- License --></span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><</span></span><span leaf="">dependency</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><</span></span><span leaf="">groupId</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf="">de.schlichtherle.truelicense</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><!--/</span--></span><span leaf="">groupId</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><</span></span><span leaf="">artifactId</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf="">truelicense-core</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><!--/</span--></span><span leaf="">artifactId</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><</span></span><span leaf="">version</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf="">1.33</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><!--/</span--></span><span leaf="">version</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><!--/</span--></span><span leaf="">dependency</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf=""><br></span></span></span></span></span></code></pre> <h4 data-sourcepos="214:1-214:22" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 16px;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">License 校验类</span></h4> <p data-sourcepos="215:1-215:51" style="box-sizing: border-box;margin-top: 0px;margin-bottom: 1rem;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span leaf="">创建</span><span leaf=""> </span><code style="box-sizing: border-box;font-family: SFMono-Regular, Consolas, " liberation mono, menlo, monospace;font-size: 13.6px;padding: 0.2rem 0.4rem;margin: 0px;background-color: rgb(247, 248, 248);color: rgb(9, 132, 79);border-radius: 0.1875rem;><span leaf="">com.icoderoad.license.LicenseVerify</span></code><span leaf=""> </span><span leaf="">类:</span></p> <pre data-sourcepos="217:1-279:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">package</span></span><span leaf=""> </span><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">com</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">icoderoad</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">de</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">schlichtherle</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;"><span leaf="">*</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">lombok</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Data</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">lombok</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">extern</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">slf4j</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Slf4j</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">io</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">File</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">text</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">DateFormat</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">text</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">MessageFormat</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">text</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">SimpleDateFormat</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">util</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">prefs</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Preferences</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Slf4j</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseVerify</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(142, 156, 146);"><span leaf="">// 安装 License 证书</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">synchronized</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseContent</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">install</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseVerifyParam</span></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseContent</span></span><span leaf=""> result </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">null</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">DateFormat</span></span><span leaf=""> format </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">SimpleDateFormat</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"yyyy-MM-dd HH:mm:ss"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">try</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseManager</span></span><span leaf=""> licenseManager </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseManagerHolder</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getInstance</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">initLicenseParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> licenseManager</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">uninstall</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> result </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span leaf=""> licenseManager</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">install</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">File</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getLicensePath</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> log</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">info</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">MessageFormat</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">format</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"证书安装成功,证书有效期:{0} - {1}"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""><br></span><span leaf=""> format</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">format</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">result</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getNotBefore</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> format</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">format</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">result</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getNotAfter</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">catch</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Exception</span></span><span leaf=""> e</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> log</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">error</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"证书安装失败: {}"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> e</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getMessage</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span leaf=""> result</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(142, 156, 146);"><span leaf="">// 校验 License 证书</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">boolean</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">verify</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseManager</span></span><span leaf=""> licenseManager </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseManagerHolder</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getInstance</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">null</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">DateFormat</span></span><span leaf=""> format </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">SimpleDateFormat</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"yyyy-MM-dd HH:mm:ss"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">try</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseContent</span></span><span leaf=""> licenseContent </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span leaf=""> licenseManager</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">verify</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> log</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">info</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">MessageFormat</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">format</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"证书校验通过,证书有效期:{0} - {1}"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""><br></span><span leaf=""> format</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">format</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">licenseContent</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getNotBefore</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> format</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">format</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">licenseContent</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getNotAfter</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">true</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">catch</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Exception</span></span><span leaf=""> e</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> log</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">error</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"证书校验失败: {}"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> e</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getMessage</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">false</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(142, 156, 146);"><span leaf="">// 初始化证书生成参数</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseParam</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">initLicenseParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseVerifyParam</span></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Preferences</span></span><span leaf=""> preferences </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Preferences</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">userNodeForPackage</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseVerify</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">CipherParam</span></span><span leaf=""> cipherParam </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">DefaultCipherParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getStorePass</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">KeyStoreParam</span></span><span leaf=""> publicStoreParam </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">CustomKeyStoreParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseVerify</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getPublicKeysStorePath</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getPublicAlias</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getStorePass</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">null</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">DefaultLicenseParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getSubject</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> preferences</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> publicStoreParam</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> cipherParam</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span></code></pre> <h4 data-sourcepos="281:1-281:37" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 16px;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">License 校验类需要的参数</span></h4> <pre data-sourcepos="283:1-294:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">package</span></span><span leaf=""> </span><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">com</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">icoderoad</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Data</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseVerifyParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> subject</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> publicAlias</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> storePass</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> licensePath</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> publicKeysStorePath</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span></code></pre> <h4 data-sourcepos="296:1-296:30" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 16px;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">自定义</span><span leaf=""> </span><code style="box-sizing: border-box;font-family: SFMono-Regular, Consolas, " liberation mono, menlo, monospace;font-size: 13.6px;padding: 0.2rem 0.4rem;margin: 0px;background-color: rgb(247, 248, 248);color: rgb(9, 132, 79);border-radius: 0.1875rem;><span leaf="">KeyStoreParam</span></code></h4> <pre data-sourcepos="298:1-342:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">package</span></span><span leaf=""> </span><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">com</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">icoderoad</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">de</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">schlichtherle</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">AbstractKeyStoreParam</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">io</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">IOException</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">io</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">InputStream</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">nio</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">file</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Files</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">nio</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">file</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Paths</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">CustomKeyStoreParam</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">extends</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">AbstractKeyStoreParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">final</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> storePath</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">final</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> alias</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">final</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> storePwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">final</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> keyPwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">CustomKeyStoreParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Class</span></span><span leaf=""> clazz</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> resource</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> alias</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> storePwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> keyPwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">super</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">clazz</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> resource</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">this</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">storePath </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span leaf=""> resource</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">this</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">alias </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span leaf=""> alias</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">this</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">storePwd </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span leaf=""> storePwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">this</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">keyPwd </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span leaf=""> keyPwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getAlias</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span leaf=""> alias</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getStorePwd</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span leaf=""> storePwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getKeyPwd</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span leaf=""> keyPwd</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">InputStream</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getStream</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">throws</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">IOException</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Files</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">newInputStream</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Paths</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">get</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">storePath</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span></code></pre> <h4 data-sourcepos="344:1-344:29" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 16px;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">LicenseManager 的单例</span></h4> <pre data-sourcepos="346:1-366:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">package</span></span><span leaf=""> </span><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">com</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">icoderoad</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">de</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">schlichtherle</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseManager</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">de</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">schlichtherle</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseParam</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseManagerHolder</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">static</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">volatile</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseManager</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">LICENSE_MANAGER</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">static</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseManager</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getInstance</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseParam</span></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">if</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">LICENSE_MANAGER</span></span><span style="box-sizing: border-box;"><span leaf="">==</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">null</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">synchronized</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseManagerHolder</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">if</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">LICENSE_MANAGER</span></span><span style="box-sizing: border-box;"><span leaf="">==</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">null</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">LICENSE_MANAGER</span></span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseManager</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">LICENSE_MANAGER</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span></code></pre> <h4 data-sourcepos="368:1-368:32" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 16px;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">项目启动时安装证书</span></h4> <h5 data-sourcepos="369:1-369:37" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 0.875rem;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><code style="box-sizing: border-box;font-family: SFMono-Regular, Consolas, " liberation mono, menlo, monospace;font-size: 11.9px;padding: 0.2rem 0.4rem;margin: 0px;background-color: rgb(247, 248, 248);color: rgb(9, 132, 79);border-radius: 0.1875rem;><span leaf="">application.properties</span></code><span leaf=""> </span><span leaf="">配置</span></h5> <pre data-sourcepos="370:1-375:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(142, 156, 146);"><span leaf=""># License 配置</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">license.subject</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">license</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">license.publicAlias</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">myKeyPass123</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">license.storePass</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">myStorePass123</span></span><span leaf=""><br></span></code></pre> <h5 data-sourcepos="377:1-377:30" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 0.875rem;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><code style="box-sizing: border-box;font-family: SFMono-Regular, Consolas, " liberation mono, menlo, monospace;font-size: 11.9px;padding: 0.2rem 0.4rem;margin: 0px;background-color: rgb(247, 248, 248);color: rgb(9, 132, 79);border-radius: 0.1875rem;><span leaf="">LicenseCheckRunner</span></code><span leaf=""> </span><span leaf="">类</span></h5> <pre data-sourcepos="379:1-418:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">package</span></span><span leaf=""> </span><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">com</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">icoderoad</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">lombok</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">extern</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">slf4j</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Slf4j</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">org</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">springframework</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">beans</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">factory</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">annotation</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Value</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">org</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">springframework</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">boot</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">ApplicationArguments</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">org</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">springframework</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">boot</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">ApplicationRunner</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">org</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">springframework</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">stereotype</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Component</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Slf4j</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Component</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCheckRunner</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">implements</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">ApplicationRunner</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Value</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"${license.subject}"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> subject</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Value</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"${license.publicAlias}"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> publicAlias</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Value</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"${license.storePass}"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">private</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> storePass</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">void</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">run</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">ApplicationArguments</span></span><span leaf=""> args</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">throws</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Exception</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> log</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">info</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"++++++++ 开始安装证书 ++++++++"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseVerifyParam</span></span><span leaf=""> param </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseVerifyParam</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setSubject</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">subject</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setPublicAlias</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">publicAlias</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setStorePass</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">storePass</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span leaf=""> resourcePath </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getClass</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getClassLoader</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getResource</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">""</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getPath</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setLicensePath</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">resourcePath </span><span style="box-sizing: border-box;"><span leaf="">+</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"license.lic"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setPublicKeysStorePath</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">resourcePath </span><span style="box-sizing: border-box;"><span leaf="">+</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"publicCerts.keystore"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseVerify</span></span><span leaf=""> licenseVerify </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseVerify</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> licenseVerify</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">install</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">param</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> log</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">info</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"++++++++ 证书安装结束 ++++++++"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span></code></pre> <h4 data-sourcepos="420:1-420:20" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 16px;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">配置拦截器</span></h4> <h5 data-sourcepos="421:1-421:31" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 0.875rem;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><code style="box-sizing: border-box;font-family: SFMono-Regular, Consolas, " liberation mono, menlo, monospace;font-size: 11.9px;padding: 0.2rem 0.4rem;margin: 0px;background-color: rgb(247, 248, 248);color: rgb(9, 132, 79);border-radius: 0.1875rem;><span leaf="">LicenseCheckInterceptor</span></code></h5> <pre data-sourcepos="423:1-453:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">package</span></span><span leaf=""> </span><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">com</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">icoderoad</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">interceptor</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">com</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">icoderoad</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">license</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseVerify</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">lombok</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">extern</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">slf4j</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Slf4j</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">org</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">springframework</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">web</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">servlet</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">HandlerInterceptor</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">javax</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">servlet</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">http</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">HttpServletRequest</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">javax</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">servlet</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">http</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">HttpServletResponse</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">util</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">HashMap</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">java</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">util</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Map</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Slf4j</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCheckInterceptor</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">implements</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">HandlerInterceptor</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">boolean</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">preHandle</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">HttpServletRequest</span></span><span leaf=""> request</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">HttpServletResponse</span></span><span leaf=""> response</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Object</span></span><span leaf=""> handler</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">throws</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Exception</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseVerify</span></span><span leaf=""> licenseVerify </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseVerify</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">boolean</span></span><span leaf=""> verifyResult </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span leaf=""> licenseVerify</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">verify</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">if</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">verifyResult</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">true</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">else</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> response</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">setCharacterEncoding</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"utf-8"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Map</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">String</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span leaf=""> result </span><span style="box-sizing: border-box;"><span leaf="">=</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">HashMap</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf=""><</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">></span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">1</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> result</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">put</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"result"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">,</span></span><span style="box-sizing: border-box;color: rgb(211, 45, 38);"><span leaf="">"您的证书无效,请核查服务器是否取得授权或重新申请证书!"</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> response</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">getWriter</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">write</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">JSON</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">toJSONString</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span leaf="">result</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">return</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">false</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span></code></pre> <h5 data-sourcepos="455:1-455:21" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 0.875rem;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">注册拦截器</span></h5> <pre data-sourcepos="457:1-472:3" tabindex="0" style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;margin: 0.5rem 0px;overflow-wrap: normal;padding: 1rem;overflow: auto;line-height: 1.45;background: rgb(247, 248, 248);border-radius: 0.1875rem;color: black;text-align: left;word-spacing: normal;word-break: normal;tab-size: 4;hyphens: none;><code style="white-space:pre-wrap;box-sizing: border-box;font-family: Consolas, Monaco, " andale mono, ubuntu monospace;font-size: 13.6px;padding: 0px;margin: 0px;background-color: initial;color: rgb(9, 132, 79);border-radius: 0.1875rem;background-image: none;background-position: 0% 0%;background-size: auto;background-repeat: repeat;background-attachment: scroll;background-origin: padding-box;background-clip: border-box;text-align: left;word-spacing: normal;word-break: normal;overflow-wrap: normal;tab-size: 4;hyphens: none;border: 0px;display: inline;overflow: visible;line-height: inherit;><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">package</span></span><span leaf=""> </span><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">com</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">icoderoad</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">config</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">com</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">icoderoad</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">interceptor</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCheckInterceptor</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">org</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">springframework</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">context</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">annotation</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">Configuration</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">org</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">springframework</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">web</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">servlet</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">config</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">annotation</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">InterceptorRegistry</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">import</span></span><span style="box-sizing: border-box;"><span style="box-sizing: border-box;opacity: 0.7;"><span leaf="">org</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">springframework</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">web</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">servlet</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">config</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span leaf="">annotation</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">WebMvcConfigurer</span></span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Configuration</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">class</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">WebMvcConfig</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">implements</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">WebMvcConfigurer</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">public</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">void</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">addInterceptors</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">InterceptorRegistry</span></span><span leaf=""> registry</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">{</span></span><span leaf=""><br></span><span leaf=""> registry</span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">.</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">addInterceptor</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(188, 49, 156);"><span leaf="">new</span></span><span style="box-sizing: border-box;color: rgb(150, 125, 65);"><span leaf="">LicenseCheckInterceptor</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">(</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">)</span></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">;</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span><span style="box-sizing: border-box;color: rgb(40, 52, 206);"><span leaf="">}</span></span><span leaf=""><br></span></code></pre> <h3 data-sourcepos="474:1-474:10" style="box-sizing: border-box;margin-top: 1.5rem;margin-bottom: 1rem;font-weight: 600;line-height: 1.25;font-size: 1.25rem;color: rgb(5, 149, 191);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-style: normal;font-variant-caps: normal;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span style="box-sizing: border-box;display: inline-block;fill: currentcolor;vertical-align: middle;color: rgb(5, 149, 191);visibility: hidden;"></span><span leaf="">总结</span></h3> <p data-sourcepos="476:1-476:223" style="box-sizing: border-box;margin-top: 0px;margin-bottom: 1rem;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span leaf="">本文系统性地阐述了在</span><span leaf=""> </span><strong style="box-sizing: border-box;font-weight: 600;color: rgb(51, 51, 51);"><span leaf="">SpringBoot</span></strong><span leaf=""> </span><span leaf="">项目中实现 License 认证的简洁方案。从背景概述到实现细节,我们深入探讨了如何通过生成密钥对和证书实现高效的 License 校验机制。</span></p> <p data-sourcepos="478:1-479:300" style="box-sizing: border-box;margin-top: 0px;margin-bottom: 0px !important;caret-color: rgb(51, 51, 51);color: rgb(51, 51, 51);font-family: -apple-system, BlinkMacSystemFont, " segoe ui, helvetica, arial, sans-serif, apple color emoji, segoe ui emoji;font-size: 16px;font-style: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: auto;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: auto;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration: none;><span leaf="">通过使用</span><span leaf=""> </span><strong style="box-sizing: border-box;font-weight: 600;color: rgb(51, 51, 51);"><span leaf="">TrueLicense</span></strong><span leaf=""> </span><span leaf="">工具,开发者能够快速生成符合项目需求的证书,而在项目中引入 License 验证功能后,可以有效提升应用的安全性和合规性。此外,本文所介绍的方案灵活性强,适用于多种使用场景,尤其是在复杂的企业内网部署环境中具有显著优势。</span><span leaf=""><br></span><span leaf="">未来,您可以根据项目的特定需求,进一步扩展 License 认证功能,例如:绑定硬件信息、增加多级权限控制等,以实现更加精细化的授权管理。希望本篇文章能够为您提供切实可行的技术思路,助力构建专业的 License 认证体系。</span></p>
作者:微信小助手
<p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 0px;color: rgb(10, 10, 10);font-family: ui-sans-serif, system-ui, sans-serif, " apple color emoji, segoe ui symbol, noto emoji;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;font-size: 0px;line-height: 0;><span leaf=""> </span></p> <section style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(10, 10, 10);font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;> <p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 1.5em 8px;text-align: justify;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;letter-spacing: 0.1em;color: rgb(63, 63, 63);><span leaf="">在 Java 8 引入的函数式编程支持中,</span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, " liberation mono, courier new, monospace;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 接口作为最常用的工具之一,广泛应用于各种复杂的场景。今天我们将继续探讨 GitHub 上一些非常厉害的 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 代码写法参考,这些代码在实际项目中解决了各种问题,并展示了 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 的高级技巧。我们将看到一些新的实践,远离前面提到的简单示例,而是探索更具创意和挑战性的应用。</span></p> <hr style="box-sizing: border-box;border: none;height: 1px;color: inherit;margin: 2em 0px;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, microsoft yahei, arial, sans-serif;font-size: 15px;transform-origin: 0px 0px;transform: scale(1, 0.5);background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0));> <h3 style="box-sizing: border-box;border-width: 0px 0px 1px 4px;border-style: solid solid dashed;border-bottom-color: rgb(0, 152, 116);border-left-color: rgb(0, 152, 116);font-size: 18px;font-weight: bold;margin: 2em 8px 0.75em 0px;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;padding-left: 12px;color: rgb(63, 63, 63);><span leaf="">1. </span><strong style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-weight: bold;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: inherit;color: rgb(0, 152, 116);><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 16.2px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 和 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 16.2px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Optional</span></code><span leaf=""> 配合使用</span></strong></h3> <p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 1.5em 8px;text-align: justify;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;letter-spacing: 0.1em;color: rgb(63, 63, 63);><span leaf="">在很多实际开发中,</span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Optional</span></code><span leaf=""> 用于避免空指针异常(</span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">NullPointerException</span></code><span leaf="">)。将 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 与 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Optional</span></code><span leaf=""> 配合使用可以帮助我们优雅地处理可空对象,并避免冗长的条件判断。</span></p> <h4 style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-size: 16.5px;font-weight: bold;margin: 2em 8px 0.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;color: rgb(0, 152, 116);><span leaf="">代码示例:</span></h4> <pre style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 14px;margin: 10px 8px;color: rgb(171, 178, 191);background: rgb(40, 44, 52);text-align: left;line-height: 1.5;overflow-x: auto;border-radius: 8px;box-shadow: rgba(0, 0, 0.05) 0px inset;padding: !important;><span hidden style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));display: flex;padding: 10px 14px 0px;"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" width="45px" height="13px" viewbox="0 0 450 130"> <ellipse cx="50" cy="65" rx="50" ry="52" stroke="rgb(220,60,54)" stroke-width="2" fill="rgb(237,108,96)"></ellipse><ellipse cx="225" cy="65" rx="50" ry="52" stroke="rgb(218,151,33)" stroke-width="2" fill="rgb(247,193,81)"></ellipse><ellipse cx="400" cy="65" rx="50" ry="52" stroke="rgb(27,161,37)" stroke-width="2" fill="rgb(100,200,86)"></ellipse> </svg></span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: " fira code, menlo, operator mono, consolas, monaco, monospace;font-feature-settings: normal;font-variation-settings: normal;font-size: 15px;display: -webkit-box;padding: 0.5em 1em 1em;overflow-x: auto;text-indent: 0px;text-align: left;line-height: 1.75;margin: 0px;white-space: pre-wrap;><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">import</span></span><span leaf=""> java.util.Optional;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">import</span></span><span leaf=""> java.util.function.Function;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">public</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">class</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">FunctionWithOptional</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">public</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">static</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">void</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(97, 174, 238);"><span leaf="">main</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf="">(String[] args)</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 定义一个 User 类</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">class</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">User</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> String name;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">int</span></span><span leaf=""> age;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> User(String name, </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">int</span></span><span leaf=""> age) {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">this</span></span><span leaf="">.name = name;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">this</span></span><span leaf="">.age = age;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> }</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> }</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 使用 Optional 和 Function 提取用户年龄</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> Function <user, optional<integer>> getAge = user -> Optional.ofNullable(user).map(u -> u.age); </user,></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 创建一个 User 对象</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">User</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">user</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">=</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">new</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">User</span></span><span leaf="">(</span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Alice"</span></span><span leaf="">, </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">30</span></span><span leaf="">);</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 使用 Optional 来安全地获取年龄</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> Optional <integer> age = getAge.apply(user); </integer></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> age.ifPresent(a -> System.out.println(</span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"User's age: "</span></span><span leaf=""> + a)); </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 输出 User's age: 30</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 使用 null 时,返回空 Optional</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> age = getAge.apply(</span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(86, 182, 194);"><span leaf="">null</span></span><span leaf="">);</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> age.ifPresent(a -> System.out.println(</span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"User's age: "</span></span><span leaf=""> + a)); </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 不输出任何内容</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> }</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf="">}</span></code></pre> <h4 style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-size: 16.5px;font-weight: bold;margin: 2em 8px 0.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;color: rgb(0, 152, 116);><span leaf="">解释:</span></h4> <ul style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));list-style: none;margin: 0px;padding: 0px 0px 0px 1.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;color: rgb(63, 63, 63); class="list-paddingleft-1"> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">getAge</span></code><span leaf=""> 是一个 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf="">,它接收 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">User</span></code><span leaf=""> 对象,并使用 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Optional</span></code><span leaf=""> 包装返回的结果。这样可以优雅地处理空值情况,避免了手动检查 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">null</span></code><span leaf="">。</span> </section></li> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• 通过 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">map()</span></code><span leaf=""> 方法,只有在 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">user</span></code><span leaf=""> 非 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">null</span></code><span leaf=""> 时才会提取 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">age</span></code><span leaf="">,否则返回 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Optional.empty()</span></code><span leaf="">,避免了异常的发生。</span> </section></li> </ul> <p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 1.5em 8px;text-align: justify;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;letter-spacing: 0.1em;color: rgb(63, 63, 63);><span leaf="">这种方式在链式调用中非常有用,可以高效地避免 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">NullPointerException</span></code><span leaf="">。</span></p> <hr style="box-sizing: border-box;border: none;height: 1px;color: inherit;margin: 2em 0px;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, microsoft yahei, arial, sans-serif;font-size: 15px;transform-origin: 0px 0px;transform: scale(1, 0.5);background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0));> <h2 style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-size: 19.5px;font-weight: bold;margin: 4em auto 2em;text-align: center;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;display: table;padding: 0.3em 1em;color: rgb(255, 255, 255);background: rgb(0, 152, 116);border-radius: 8px;box-shadow: rgba(0, 0, 0.1) 0px 4px 6px;><span leaf="">2. </span><strong style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-weight: bold;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: inherit;color: rgb(0, 152, 116);><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 17.55px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 和 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 17.55px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Predicate</span></code><span leaf=""> 联合使用进行过滤</span></strong></h2> <p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 1.5em 8px;text-align: justify;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;letter-spacing: 0.1em;color: rgb(63, 63, 63);><span leaf="">在处理数据集合时,我们经常需要对数据进行过滤并进行转换,使用 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 和 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Predicate</span></code><span leaf=""> 联合能够简洁地实现这一功能。例如,可以先使用 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Predicate</span></code><span leaf=""> 筛选符合条件的数据,再使用 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 转换数据的形式。</span></p> <h4 style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-size: 16.5px;font-weight: bold;margin: 2em 8px 0.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;color: rgb(0, 152, 116);><span leaf="">代码示例:</span></h4> <pre style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 14px;margin: 10px 8px;color: rgb(171, 178, 191);background: rgb(40, 44, 52);text-align: left;line-height: 1.5;overflow-x: auto;border-radius: 8px;box-shadow: rgba(0, 0, 0.05) 0px inset;padding: !important;><span hidden style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));display: flex;padding: 10px 14px 0px;"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" width="45px" height="13px" viewbox="0 0 450 130"> <ellipse cx="50" cy="65" rx="50" ry="52" stroke="rgb(220,60,54)" stroke-width="2" fill="rgb(237,108,96)"></ellipse><ellipse cx="225" cy="65" rx="50" ry="52" stroke="rgb(218,151,33)" stroke-width="2" fill="rgb(247,193,81)"></ellipse><ellipse cx="400" cy="65" rx="50" ry="52" stroke="rgb(27,161,37)" stroke-width="2" fill="rgb(100,200,86)"></ellipse> </svg></span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: " fira code, menlo, operator mono, consolas, monaco, monospace;font-feature-settings: normal;font-variation-settings: normal;font-size: 15px;display: -webkit-box;padding: 0.5em 1em 1em;overflow-x: auto;text-indent: 0px;text-align: left;line-height: 1.75;margin: 0px;white-space: pre-wrap;><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">import</span></span><span leaf=""> java.util.List;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">import</span></span><span leaf=""> java.util.function.Function;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">import</span></span><span leaf=""> java.util.function.Predicate;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">import</span></span><span leaf=""> java.util.stream.Collectors;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">public</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">class</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">FunctionWithPredicate</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">public</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">static</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">void</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(97, 174, 238);"><span leaf="">main</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf="">(String[] args)</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 假设我们有一个 User 类</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">class</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">User</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> String name;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">int</span></span><span leaf=""> age;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> User(String name, </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">int</span></span><span leaf=""> age) {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">this</span></span><span leaf="">.name = name;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">this</span></span><span leaf="">.age = age;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> }</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(97, 174, 238);"><span leaf="">@Override</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">public</span></span><span leaf=""> String </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(97, 174, 238);"><span leaf="">toString</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf="">()</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">return</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"User{name='"</span></span><span leaf=""> + name + </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"', age="</span></span><span leaf=""> + age + </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"}"</span></span><span leaf="">;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> }</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> }</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 创建一组 User 数据</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> List <user> users = List.of( </user></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">new</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">User</span></span><span leaf="">(</span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Alice"</span></span><span leaf="">, </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">25</span></span><span leaf="">),</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">new</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">User</span></span><span leaf="">(</span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Bob"</span></span><span leaf="">, </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">35</span></span><span leaf="">),</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">new</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">User</span></span><span leaf="">(</span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Charlie"</span></span><span leaf="">, </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">28</span></span><span leaf="">),</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">new</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">User</span></span><span leaf="">(</span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"David"</span></span><span leaf="">, </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">40</span></span><span leaf="">)</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> );</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 定义一个 Predicate,筛选年龄大于 30 的用户</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> Predicate <user> isOlderThan30 = user -> user.age > </user></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">30</span></span><span leaf="">;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 定义一个 Function,提取用户的姓名</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> Function <user, string> getName = user -> user.name; </user,></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 筛选年龄大于 30 的用户并提取姓名</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> List <string> names = users.stream() </string></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> .filter(isOlderThan30) </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 使用 Predicate 进行筛选</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> .map(getName) </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 使用 Function 转换数据</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> .collect(Collectors.toList());</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> System.out.println(names); </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 输出 [Bob, David]</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> }</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf="">}</span></code></pre> <h4 style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-size: 16.5px;font-weight: bold;margin: 2em 8px 0.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;color: rgb(0, 152, 116);><span leaf="">解释:</span></h4> <ul style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));list-style: none;margin: 0px;padding: 0px 0px 0px 1.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;color: rgb(63, 63, 63); class="list-paddingleft-1"> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">isOlderThan30</span></code><span leaf=""> 是一个 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Predicate</span></code><span leaf="">,用于判断用户是否年纪大于 30。</span> </section></li> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">getName</span></code><span leaf=""> 是一个 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf="">,将 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">User</span></code><span leaf=""> 对象转换为 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">String</span></code><span leaf=""> 类型(即用户的姓名)。</span> </section></li> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• 通过 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">filter</span></code><span leaf=""> 和 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">map</span></code><span leaf=""> 的结合,我们能够高效地筛选出符合条件的用户,并转换成所需的数据格式。</span> </section></li> </ul> <p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 1.5em 8px;text-align: justify;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;letter-spacing: 0.1em;color: rgb(63, 63, 63);><span leaf="">这种方法让我们能够以更简洁的方式处理集合中的数据,避免了显式的 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">for</span></code><span leaf=""> 循环,提高了代码的可读性和可维护性。</span></p> <hr style="box-sizing: border-box;border: none;height: 1px;color: inherit;margin: 2em 0px;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, microsoft yahei, arial, sans-serif;font-size: 15px;transform-origin: 0px 0px;transform: scale(1, 0.5);background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0));> <h3 style="box-sizing: border-box;border-width: 0px 0px 1px 4px;border-style: solid solid dashed;border-bottom-color: rgb(0, 152, 116);border-left-color: rgb(0, 152, 116);font-size: 18px;font-weight: bold;margin: 2em 8px 0.75em 0px;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;padding-left: 12px;color: rgb(63, 63, 63);><span leaf="">3. </span><strong style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-weight: bold;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: inherit;color: rgb(0, 152, 116);><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 16.2px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 和 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 16.2px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Consumer</span></code><span leaf=""> 联合处理异步任务</span></strong></h3> <p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 1.5em 8px;text-align: justify;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;letter-spacing: 0.1em;color: rgb(63, 63, 63);><span leaf="">异步编程是现代应用中常见的模式,尤其是在处理 I/O 密集型任务时。</span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 和 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Consumer</span></code><span leaf=""> 可以联合使用,用于处理异步回调中的数据流。</span></p> <h4 style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-size: 16.5px;font-weight: bold;margin: 2em 8px 0.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;color: rgb(0, 152, 116);><span leaf="">代码示例:</span></h4> <pre style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 14px;margin: 10px 8px;color: rgb(171, 178, 191);background: rgb(40, 44, 52);text-align: left;line-height: 1.5;overflow-x: auto;border-radius: 8px;box-shadow: rgba(0, 0, 0.05) 0px inset;padding: !important;><span hidden style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));display: flex;padding: 10px 14px 0px;"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" width="45px" height="13px" viewbox="0 0 450 130"> <ellipse cx="50" cy="65" rx="50" ry="52" stroke="rgb(220,60,54)" stroke-width="2" fill="rgb(237,108,96)"></ellipse><ellipse cx="225" cy="65" rx="50" ry="52" stroke="rgb(218,151,33)" stroke-width="2" fill="rgb(247,193,81)"></ellipse><ellipse cx="400" cy="65" rx="50" ry="52" stroke="rgb(27,161,37)" stroke-width="2" fill="rgb(100,200,86)"></ellipse> </svg></span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: " fira code, menlo, operator mono, consolas, monaco, monospace;font-feature-settings: normal;font-variation-settings: normal;font-size: 15px;display: -webkit-box;padding: 0.5em 1em 1em;overflow-x: auto;text-indent: 0px;text-align: left;line-height: 1.75;margin: 0px;white-space: pre-wrap;><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">import</span></span><span leaf=""> java.util.concurrent.CompletableFuture;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">import</span></span><span leaf=""> java.util.function.Function;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">import</span></span><span leaf=""> java.util.function.Consumer;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">public</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">class</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">FunctionWithConsumerAsync</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">public</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">static</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">void</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(97, 174, 238);"><span leaf="">main</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf="">(String[] args)</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 假设我们有一个异步任务:获取用户信息</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> Function <integer, completablefuture<string>> fetchUserInfo = userId -> </integer,></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> CompletableFuture.supplyAsync(() -> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"User"</span></span><span leaf=""> + userId);</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 定义一个 Consumer 用于处理异步结果</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> Consumer <string> printUserInfo = userInfo -> System.out.println( </string></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Fetched user info: "</span></span><span leaf=""> + userInfo);</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 异步获取用户信息并处理</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> fetchUserInfo.apply(</span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">123</span></span><span leaf="">)</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> .thenAccept(printUserInfo); </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 使用 Consumer 处理结果</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> }</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf="">}</span></code></pre> <h4 style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-size: 16.5px;font-weight: bold;margin: 2em 8px 0.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;color: rgb(0, 152, 116);><span leaf="">解释:</span></h4> <ul style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));list-style: none;margin: 0px;padding: 0px 0px 0px 1.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;color: rgb(63, 63, 63); class="list-paddingleft-1"> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">fetchUserInfo</span></code><span leaf=""> 是一个异步任务,它返回一个 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">CompletableFuture</span></code><span leaf="">,该异步任务会根据用户 ID 获取用户信息。</span> </section></li> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">printUserInfo</span></code><span leaf=""> 是一个 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Consumer</span></code><span leaf="">,用于处理异步回调结果,打印用户信息。</span> </section></li> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• 使用 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">thenAccept()</span></code><span leaf=""> 方法将 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Consumer</span></code><span leaf=""> 应用到异步结果上,这样可以在数据准备好后异步执行处理逻辑。</span> </section></li> </ul> <p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 1.5em 8px;text-align: justify;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;letter-spacing: 0.1em;color: rgb(63, 63, 63);><span leaf="">通过这种方式,我们可以清晰地将数据的获取与后续处理分离,使得异步编程变得更加简洁和易于理解。</span></p> <hr style="box-sizing: border-box;border: none;height: 1px;color: inherit;margin: 2em 0px;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, microsoft yahei, arial, sans-serif;font-size: 15px;transform-origin: 0px 0px;transform: scale(1, 0.5);background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0));> <h3 style="box-sizing: border-box;border-width: 0px 0px 1px 4px;border-style: solid solid dashed;border-bottom-color: rgb(0, 152, 116);border-left-color: rgb(0, 152, 116);font-size: 18px;font-weight: bold;margin: 2em 8px 0.75em 0px;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;padding-left: 12px;color: rgb(63, 63, 63);><span leaf="">4. </span><strong style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-weight: bold;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: inherit;color: rgb(0, 152, 116);><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 16.2px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 与高阶函数:动态创建多个转换器</span></strong></h3> <p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 1.5em 8px;text-align: justify;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;letter-spacing: 0.1em;color: rgb(63, 63, 63);><span leaf="">在一些复杂的应用场景中,我们可能需要根据不同的条件动态创建多个转换器,并将它们组合起来执行。通过高阶函数,我们可以非常灵活地实现这一需求。</span></p> <h4 style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-size: 16.5px;font-weight: bold;margin: 2em 8px 0.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;color: rgb(0, 152, 116);><span leaf="">代码示例:</span></h4> <pre style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 14px;margin: 10px 8px;color: rgb(171, 178, 191);background: rgb(40, 44, 52);text-align: left;line-height: 1.5;overflow-x: auto;border-radius: 8px;box-shadow: rgba(0, 0, 0.05) 0px inset;padding: !important;><span hidden style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));display: flex;padding: 10px 14px 0px;"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" width="45px" height="13px" viewbox="0 0 450 130"> <ellipse cx="50" cy="65" rx="50" ry="52" stroke="rgb(220,60,54)" stroke-width="2" fill="rgb(237,108,96)"></ellipse><ellipse cx="225" cy="65" rx="50" ry="52" stroke="rgb(218,151,33)" stroke-width="2" fill="rgb(247,193,81)"></ellipse><ellipse cx="400" cy="65" rx="50" ry="52" stroke="rgb(27,161,37)" stroke-width="2" fill="rgb(100,200,86)"></ellipse> </svg></span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: " fira code, menlo, operator mono, consolas, monaco, monospace;font-feature-settings: normal;font-variation-settings: normal;font-size: 15px;display: -webkit-box;padding: 0.5em 1em 1em;overflow-x: auto;text-indent: 0px;text-align: left;line-height: 1.75;margin: 0px;white-space: pre-wrap;><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">import</span></span><span leaf=""> java.util.function.Function;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">public</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">class</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">HigherOrderFunction</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">public</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">static</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">void</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(97, 174, 238);"><span leaf="">main</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf="">(String[] args)</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 定义一个高阶函数,生成基于某些条件的转换器</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> Function <string, function<integer, string>> createConverter = condition -> { </string,></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">if</span></span><span leaf=""> (</span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"prefix"</span></span><span leaf="">.equals(condition)) {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">return</span></span><span leaf=""> number -> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Prefix_"</span></span><span leaf=""> + number;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> } </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">else</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">if</span></span><span leaf=""> (</span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"suffix"</span></span><span leaf="">.equals(condition)) {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">return</span></span><span leaf=""> number -> number + </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"_Suffix"</span></span><span leaf="">;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> } </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">else</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">return</span></span><span leaf=""> number -> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"NoConversion_"</span></span><span leaf=""> + number;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> }</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> };</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 根据不同条件创建转换器</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> Function <integer, string> prefixConverter = createConverter.apply( </integer,></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"prefix"</span></span><span leaf="">);</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> Function <integer, string> suffixConverter = createConverter.apply( </integer,></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"suffix"</span></span><span leaf="">);</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 使用生成的转换器</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> System.out.println(prefixConverter.apply(</span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">123</span></span><span leaf="">)); </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 输出 Prefix_123</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> System.out.println(suffixConverter.apply(</span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">123</span></span><span leaf="">)); </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 输出 123_Suffix</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> }</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf="">}</span></code></pre> <h4 style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-size: 16.5px;font-weight: bold;margin: 2em 8px 0.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;color: rgb(0, 152, 116);><span leaf="">解释:</span></h4> <ul style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));list-style: none;margin: 0px;padding: 0px 0px 0px 1.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;color: rgb(63, 63, 63); class="list-paddingleft-1"> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">createConverter</span></code><span leaf=""> 是一个高阶函数,根据传入的条件动态生成不同的 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf="">。</span> </section></li> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">prefixConverter</span></code><span leaf=""> 和 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">suffixConverter</span></code><span leaf=""> 是基于条件生成的转换器,分别为整数加上前缀或后缀。</span> </section></li> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• 这种方式让我们能够根据不同的业务需求动态创建转换逻辑,避免了大量的条件判断语句。</span> </section></li> </ul> <p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 1.5em 8px;text-align: justify;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;letter-spacing: 0.1em;color: rgb(63, 63, 63);><span leaf="">通过这种高阶函数的技巧,我们可以在更复杂的应用中实现更加灵活和可维护的转换逻辑。</span></p> <hr style="box-sizing: border-box;border: none;height: 1px;color: inherit;margin: 2em 0px;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, microsoft yahei, arial, sans-serif;font-size: 15px;transform-origin: 0px 0px;transform: scale(1, 0.5);background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0));> <h3 style="box-sizing: border-box;border-width: 0px 0px 1px 4px;border-style: solid solid dashed;border-bottom-color: rgb(0, 152, 116);border-left-color: rgb(0, 152, 116);font-size: 18px;font-weight: bold;margin: 2em 8px 0.75em 0px;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;padding-left: 12px;color: rgb(63, 63, 63);><span leaf="">5. </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 16.2px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 与集合的组合:链式操作</span></h3> <p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 1.5em 8px;text-align: justify;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;letter-spacing: 0.1em;color: rgb(63, 63, 63);><span leaf="">链式操作是函数式编程中的一种常见模式,通过将多个 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 组合在一起,可以实现复杂的转换逻辑。这对于处理集合数据非常有用。</span></p> <h4 style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-size: 16.5px;font-weight: bold;margin: 2em 8px 0.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;color: rgb(0, 152, 116);><span leaf="">代码示例:</span></h4> <pre style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 14px;margin: 10px 8px;color: rgb(171, 178, 191);background: rgb(40, 44, 52);text-align: left;line-height: 1.5;overflow-x: auto;border-radius: 8px;box-shadow: rgba(0, 0, 0.05) 0px inset;padding: !important;><span hidden style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));display: flex;padding: 10px 14px 0px;"> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" width="45px" height="13px" viewbox="0 0 450 130"> <ellipse cx="50" cy="65" rx="50" ry="52" stroke="rgb(220,60,54)" stroke-width="2" fill="rgb(237,108,96)"></ellipse><ellipse cx="225" cy="65" rx="50" ry="52" stroke="rgb(218,151,33)" stroke-width="2" fill="rgb(247,193,81)"></ellipse><ellipse cx="400" cy="65" rx="50" ry="52" stroke="rgb(27,161,37)" stroke-width="2" fill="rgb(100,200,86)"></ellipse> </svg></span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: " fira code, menlo, operator mono, consolas, monaco, monospace;font-feature-settings: normal;font-variation-settings: normal;font-size: 15px;display: -webkit-box;padding: 0.5em 1em 1em;overflow-x: auto;text-indent: 0px;text-align: left;line-height: 1.75;margin: 0px;white-space: pre-wrap;><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">import</span></span><span leaf=""> java.util.List;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">import</span></span><span leaf=""> java.util.function.Function;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">import</span></span><span leaf=""> java.util.stream.Collectors;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">public</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">class</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(230, 192, 123);"><span leaf="">FunctionChainWithCollections</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">public</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">static</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">void</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(97, 174, 238);"><span leaf="">main</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf="">(String[] args)</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 创建一组用户年龄数据</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> List <integer> ages = List.of( </integer></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">25</span></span><span leaf="">, </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">30</span></span><span leaf="">, </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">35</span></span><span leaf="">, </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">40</span></span><span leaf="">, </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">45</span></span><span leaf="">);</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 定义一个 Function,表示年龄到年龄段的转换</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> Function <integer, string> ageToRange = age -> { </integer,></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">if</span></span><span leaf=""> (age < </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">30</span></span><span leaf="">) {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">return</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Young"</span></span><span leaf="">;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> } </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">else</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">if</span></span><span leaf=""> (age < </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(209, 154, 102);"><span leaf="">40</span></span><span leaf="">) {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">return</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Middle-aged"</span></span><span leaf="">;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> } </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">else</span></span><span leaf=""> {</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">return</span></span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Old"</span></span><span leaf="">;</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> }</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> };</span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> </span><span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 定义一个 Function,表示将年龄段转换为推荐的健康活动</span></span><br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"><span leaf=""> Function <string, string< span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf="">> rangeToActivity = range -> {</span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> </span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">switch</span></span> <span leaf=""> (range) {</span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> </span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">case</span></span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Young"</span></span> <span leaf="">: </span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">return</span></span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Running"</span></span> <span leaf="">;</span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> </span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">case</span></span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Middle-aged"</span></span> <span leaf="">: </span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">return</span></span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Cycling"</span></span> <span leaf="">;</span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> </span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">case</span></span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Old"</span></span> <span leaf="">: </span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">return</span></span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Walking"</span></span> <span leaf="">;</span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> </span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">default</span></span> <span leaf="">: </span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(249, 38, 114);"><span leaf="">return</span></span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(152, 195, 121);"><span leaf="">"Unknown"</span></span> <span leaf="">;</span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> }</span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> };</span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> </span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 使用链式操作处理年龄数据</span></span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> List <string> activities = ages.stream() </string></span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> .map(ageToRange) </span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 将年龄转换为年龄段</span></span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> .map(rangeToActivity) </span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 将年龄段转换为活动推荐</span></span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> .collect(Collectors.toList());</span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> System.out.println(activities); </span> <span style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));color: rgb(177, 142, 177);font-style: italic;"><span leaf="">// 输出 [Running, Running, Cycling, Cycling, Walking]</span></span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf=""> }</span> <br style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));"> <span leaf="">}</span> </string,></span></code></pre> <h4 style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-size: 16.5px;font-weight: bold;margin: 2em 8px 0.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;color: rgb(0, 152, 116);><span leaf="">解释:</span></h4> <ul style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));list-style: none;margin: 0px;padding: 0px 0px 0px 1.5em;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;color: rgb(63, 63, 63); class="list-paddingleft-1"> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">ageToRange</span></code><span leaf=""> 将年龄转换为年龄段("Young"、"Middle-aged"、"Old")。</span> </section></li> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">rangeToActivity</span></code><span leaf=""> 将年龄段转换为健康活动推荐(如 "Running"、"Cycling" 等)。</span> </section></li> <li style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;text-indent: -1em;display: block;margin: 0.5em 8px;color: rgb(63, 63, 63);> <section> <span leaf="">• 通过链式调用,我们能够优雅地将年龄数据转换成健康活动推荐。</span> </section></li> </ul> <p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 1.5em 8px;text-align: justify;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;letter-spacing: 0.1em;color: rgb(63, 63, 63);><span leaf="">这种方法利用了 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 的组合特性,使得数据转换变得简洁、直观,并且易于扩展。</span></p> <hr style="box-sizing: border-box;border: none;height: 1px;color: inherit;margin: 2em 0px;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, microsoft yahei, arial, sans-serif;font-size: 15px;transform-origin: 0px 0px;transform: scale(1, 0.5);background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0));> <h3 style="box-sizing: border-box;border-width: 0px 0px 1px 4px;border-style: solid solid dashed;border-bottom-color: rgb(0, 152, 116);border-left-color: rgb(0, 152, 116);font-size: 18px;font-weight: bold;margin: 2em 8px 0.75em 0px;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;padding-left: 12px;color: rgb(63, 63, 63);><span leaf="">结语</span></h3> <p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 1.5em 8px;text-align: justify;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-size: 15px;letter-spacing: 0.1em;color: rgb(63, 63, 63);><span leaf="">通过这些不同的 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 使用场景,我们可以看到它的强大功能:从异步处理、懒加载、到与 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Optional</span></code><span leaf="">、</span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Predicate</span></code><span leaf=""> 等接口的结合,</span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 在 Java 开发中有着极其广泛的应用。这些实际的代码示例展示了 </span><code style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));font-family: -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 13.5px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;><span leaf="">Function</span></code><span leaf=""> 在复杂场景中的强大潜力,掌握这些技巧后,您将在开发过程中更加得心应手。</span></p> </section> <p style="box-sizing: border-box;border-width: 0px;border-style: solid;border-color: hsl(var(--border));margin: 0px;color: rgb(10, 10, 10);font-family: ui-sans-serif, system-ui, sans-serif, " apple color emoji, segoe ui symbol, noto emoji;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;font-size: 0px;line-height: 0;><span leaf=""> </span></p> <section> <span leaf=""><br></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="margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 10px;padding-right: 10px;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;font-family: Optima, PingFangSC-regular, serif;font-size: 16px;color: rgb(0, 0, 0);line-height: 1.5em;word-spacing: 0em;letter-spacing: 0em;word-break: break-word;overflow-wrap: break-word;text-align: left;"> <h2 data-tool="mdnice编辑器" style=" margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset; text-align: left;text-shadow: none;transform: none;width: 100%;-webkit-box-reflect: unset; "><span style="display: none;"></span><span style=" font-size: 22px;border-bottom-color: rgb(119, 48, 152);color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: 85%;height: auto;align-items: unset;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 10px;padding-left: 0px;padding-right: 0px; text-align: center;text-indent: 0em;text-shadow: none;transform: none;-webkit-box-reflect: unset; "><span leaf="">引言</span></span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在我们的日常开发工作中,</span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Filter</span></code><span leaf="">(过滤器)、</span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Interceptor</span></code><span leaf="">(拦截器)和 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">AOP</span></code><span leaf="">(面向切面编程)是非常常用的 3 种请求处理技术。在不同的应用场景中,使用它们都可以在不影响主业务逻辑的前提下为系统增加额外的功能。面试官去问这个问题的时候,一般是想考察求职者的技术深度和对框架机制的理解。本篇我们从 3 者的基本概念及使用来分析解答下这道面试题。</span></p> <h2 data-tool="mdnice编辑器" style=" margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset; text-align: left;text-shadow: none;transform: none;width: 100%;-webkit-box-reflect: unset; "><span style="display: none;"></span><span style=" font-size: 22px;border-bottom-color: rgb(119, 48, 152);color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: 85%;height: auto;align-items: unset;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 10px;padding-left: 0px;padding-right: 0px; text-align: center;text-indent: 0em;text-shadow: none;transform: none;-webkit-box-reflect: unset; "><span leaf="">Filter</span></span><span style="display: none;"></span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;"><span leaf="">什么是 Filter</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Filter</span></code><span leaf=""> 是 Java </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Servlet</span></code><span leaf=""> 规范的一部分,定义在 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">javax.servlet</span></code><span leaf=""> 包中,</span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Filter</span></code><span leaf=""> 可以对 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Servlet</span></code><span leaf=""> 容器的所有 HTTP 请求(</span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">HttpServletRequest</span></code><span leaf="">)和响应(</span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">HttpServletResponse</span></code><span leaf="">)进行预处理或后处理操作。例如,在请求到达目标资源之前执行身份验证或设置字符编码,或者在响应返回给客户端前修改其响应内容格式。</span></p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;"><span leaf="">Filter 接口</span></span><span style="display: none;"></span></h3> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg k0ue4mipav882cnbmffjvlrxfiaoyowabg1n9gndbfbyylu3av0epdc78k5wnsukhhozztyffw9mdqxuoquchp80rlmqpmiibl 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">package</span></span><span leaf=""> javax.servlet;</span><br><br><span style="color: #c678dd;line-height: 26px;"><span leaf="">import</span></span><span leaf=""> java.io.IOException;</span><br><br><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">interface</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">Filter</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">default</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">init</span></span><span style="line-height: 26px;"><span leaf="">(FilterConfig filterConfig)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> ServletException </span></span><span leaf="">{}</span><br><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">doFilter</span></span><span style="line-height: 26px;"><span leaf="">(ServletRequest request, ServletResponse response, FilterChain chain)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> IOException, ServletException</span></span><span leaf="">;</span><br><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">default</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">destroy</span></span><span style="line-height: 26px;"><span leaf="">()</span></span><span leaf=""> </span></span><span leaf="">{}</span><br><span leaf="">}</span><br></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">项目中自定义过滤器需实现该接口,接口中的 3 个方法就是 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Filter</span></code><span leaf=""> 的整个生命周期。</span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">init()</span></code><span leaf="">-初始化、</span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">doFilter()</span></code><span leaf="">-执行过滤逻辑、</span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">destroy()</span></code><span leaf="">-销毁。</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <p style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">init方法</span></code><span leaf="">:Web 容器在启动时,会触发每个 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Filter</span></code><span leaf=""> 实例的 init 方法调用并传递一个 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">FilterConfig</span></code><span leaf=""> 对象,该配置允许过滤器获取初始化参数以及 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">ServletContext</span></code><span leaf=""> 上下文对象,从而加载任何所需的资源。该方法在 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Filter</span></code><span leaf=""> 的整个生命周期中仅会在初始化时被调用一次。</span></p> <blockquote style="margin-top: 20px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;padding-top: 10px;padding-bottom: 10px;padding-left: 20px;padding-right: 10px;border-top-style: none;border-bottom-style: none;border-left-style: solid;border-right-style: solid;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 1px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgb(150, 84, 181);border-right-color: rgb(150, 84, 181);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;background-attachment: scroll;background-clip: border-box;background-color: rgb(251, 249, 253);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;display: block;overflow-x: auto;overflow-y: auto;"> <span style="display: none;color: rgb(0, 0, 0);font-size: 16px;line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: normal;"></span> <p style="text-indent: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0px;margin-left: 0px;"><span leaf="">该方法如果抛出异常,Web 容器就会认为这个过滤器无法正常工作,因此不会将它加入到过滤器链中,无法提供后续的请求过滤工作。</span></p> </blockquote> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <p style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">doFilter方法</span></code><span leaf="">:该方法为 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Filter</span></code><span leaf=""> 的核心工作方法,每一次请求都会调用该方法。</span></p> <blockquote style="margin-top: 20px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;padding-top: 10px;padding-bottom: 10px;padding-left: 20px;padding-right: 10px;border-top-style: none;border-bottom-style: none;border-left-style: solid;border-right-style: solid;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 1px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgb(150, 84, 181);border-right-color: rgb(150, 84, 181);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;background-attachment: scroll;background-clip: border-box;background-color: rgb(251, 249, 253);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;display: block;overflow-x: auto;overflow-y: auto;"> <span style="display: none;color: rgb(0, 0, 0);font-size: 16px;line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: normal;"></span> <p style="text-indent: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0px;margin-left: 0px;"><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">FilterChain</span></code><span leaf=""> 接口参数由具体的 Servlet 容器实现并提供。每个过滤器的 doFilter 方法都会接收一个 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">FilterChain</span></code><span leaf=""> 对象作为参数。在这个方法内部,过滤器可以选择:</span></p> </blockquote> </section></li> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">直接处理请求/响应。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">调用 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">chain.doFilter(request, response)</span></code><span leaf=""> 将请求传递给下一个过滤器或目标资源。</span> </section></li> </ul> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <p style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">destroy方法</span></code><span leaf="">:Web 容器在销毁时,会触发每个 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Filter</span></code><span leaf=""> 实例的 destroy 方法调用,清理过滤器所有持有的资源(如内存、文件句柄、线程等)。该方法在 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Filter</span></code><span leaf=""> 的整个生命周期中也仅会执行一次。</span></p> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;"><span leaf="">Filter 的配置使用</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">SpringBoot</span></code><span leaf=""> 项目中可以使用如下几种配置方式:</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">使用 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">@WebFilter</span></code><span leaf=""> 注解 + </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">@ServletComponentScan</span></code><span leaf=""> 注解</span> </section></li> </ul> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在过滤器类上使用 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">@WebFilter</span></code><span leaf=""> 注解来定义 URL 模式和其他属性</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg k0ue4mipav882cnbmffjvlrxfiaoyowabg1n9gndbfbyylu3av0epdc78k5wnsukhhozztyffw9mdqxuoquchp80rlmqpmiibl 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">package</span></span><span leaf=""> com.example.filter;</span><br><br><span style="color: #61aeee;line-height: 26px;"><span leaf="">@WebFilter</span></span><span leaf="">(urlPatterns = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"/*"</span></span><span leaf="">, filterName = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"exampleFilter"</span></span><span leaf="">)</span><br><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">ExampleFilter</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">implements</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">Filter</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">init</span></span><span style="line-height: 26px;"><span leaf="">(FilterConfig filterConfig)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> ServletException </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 初始化逻辑...</span></span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">doFilter</span></span><span style="line-height: 26px;"><span leaf="">(ServletRequest request, ServletResponse response, FilterChain chain)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> IOException, ServletException </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 传递给下一个过滤器或目标资源</span></span><br><span leaf=""> chain.doFilter(request, response);</span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">destroy</span></span><span style="line-height: 26px;"><span leaf="">()</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 清理资源...</span></span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在启动类或者任意配置类上加上 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">@ServletComponentScan</span></code><span leaf=""> 注解来让 Spring Boot 自动扫描并注册这些过滤器。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg k0ue4mipav882cnbmffjvlrxfiaoyowabg1n9gndbfbyylu3av0epdc78k5wnsukhhozztyffw9mdqxuoquchp80rlmqpmiibl 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;"><span leaf="">@SpringBootApplication</span></span><br><span style="color: #61aeee;line-height: 26px;"><span leaf="">@ServletComponentScan</span></span><span leaf="">(basePackages = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"com.example.filter"</span></span><span leaf="">) </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 指定扫描包路径</span></span><br><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">MyApplication</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">static</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">main</span></span><span style="line-height: 26px;"><span leaf="">(String[] args)</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> SpringApplication.run(MyApplication</span><span style="line-height: 26px;"><span leaf="">.</span><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf="">, </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">args</span></span><span leaf="">)</span></span><span leaf="">;</span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">使用 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">FilterRegistrationBean</span></code><span leaf=""> 进行注册</span> </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg k0ue4mipav882cnbmffjvlrxfiaoyowabg1n9gndbfbyylu3av0epdc78k5wnsukhhozztyffw9mdqxuoquchp80rlmqpmiibl 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Configuration</span></span><br><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">FilterConfig</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Bean</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> FilterRegistrationBean <examplefilter> </examplefilter></span><span style="color: #61aeee;line-height: 26px;"><span leaf="">customFilterRegistration</span></span><span style="line-height: 26px;"><span leaf="">()</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> FilterRegistrationBean <examplefilter> registrationBean = </examplefilter></span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> FilterRegistrationBean<>();</span><br><br><span leaf=""> ExampleFilter customFilter = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> ExampleFilter();</span><br><span leaf=""> registrationBean.setFilter(customFilter);</span><br><span leaf=""> registrationBean.addUrlPatterns(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"/*"</span></span><span leaf="">);</span><br><span leaf=""> registrationBean.setOrder(</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1</span></span><span leaf="">); </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 设置过滤器的执行顺序</span></span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 添加初始化参数</span></span><br><span leaf=""> registrationBean.addInitParameter(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"encoding"</span></span><span leaf="">, </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"UTF-8"</span></span><span leaf="">);</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> registrationBean;</span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">直接使用 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">@Component</span></code><span leaf=""> 注解:这种方式可以让 Spring 自动将过滤器组件化,默认会应用到所有请求路径。</span> </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg k0ue4mipav882cnbmffjvlrxfiaoyowabg1n9gndbfbyylu3av0epdc78k5wnsukhhozztyffw9mdqxuoquchp80rlmqpmiibl 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Component</span></span><br><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">ExampleFilter</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">implements</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">Filter</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">init</span></span><span style="line-height: 26px;"><span leaf="">(FilterConfig filterConfig)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> ServletException </span></span><span leaf="">{}</span><br><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">doFilter</span></span><span style="line-height: 26px;"><span leaf="">(ServletRequest request, ServletResponse response, FilterChain chain)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> IOException, ServletException </span></span><span leaf="">{</span><br><span leaf=""> chain.doFilter(request, response);</span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">destroy</span></span><span style="line-height: 26px;"><span leaf="">()</span></span><span leaf=""> </span></span><span leaf="">{}</span><br><span leaf="">}</span><br></code></pre> <h2 data-tool="mdnice编辑器" style=" margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset; text-align: left;text-shadow: none;transform: none;width: 100%;-webkit-box-reflect: unset; "><span style="display: none;"></span><span style=" font-size: 22px;border-bottom-color: rgb(119, 48, 152);color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: 85%;height: auto;align-items: unset;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 10px;padding-left: 0px;padding-right: 0px; text-align: center;text-indent: 0em;text-shadow: none;transform: none;-webkit-box-reflect: unset; "><span leaf="">Interceptor</span></span><span style="display: none;"></span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;"><span leaf="">什么是 Interceptor</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Interceptor</span></code><span leaf=""> 是 Spring MVC 框架的一部分,是位于 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">org.springframework.web.servlet</span></code><span leaf=""> 包中的 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">HandlerInterceptor</span></code><span leaf=""> 接口,用于在请求处理之前或之后执行特定逻辑。与 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Filter</span></code><span leaf=""> 不同的是,</span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Interceptor</span></code><span leaf=""> 不依赖于 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Servlet</span></code><span leaf=""> 容器,它是 Spring 框架独有的。</span></p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;"><span leaf="">HandlerInterceptor 接口</span></span><span style="display: none;"></span></h3> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg k0ue4mipav882cnbmffjvlrxfiaoyowabg1n9gndbfbyylu3av0epdc78k5wnsukhhozztyffw9mdqxuoquchp80rlmqpmiibl 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">/**</span><br><span leaf=""> * A HandlerInterceptor gets called before the appropriate HandlerAdapter triggers the execution of the handler itself.</span><br><span leaf=""> * This mechanism can be used for a large field of preprocessing aspects, e.g. for authorization checks,</span><br><span leaf=""> * or common handler behavior like locale or theme changes.</span><br><span leaf=""> * Its main purpose is to allow for factoring out repetitive handler code.</span><br><span leaf=""> */</span></span><br><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">interface</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">HandlerInterceptor</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">default</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">boolean</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">preHandle</span></span><span style="line-height: 26px;"><span leaf="">(HttpServletRequest request, HttpServletResponse response, Object handler)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> Exception </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">true</span></span><span leaf="">;</span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">default</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">postHandle</span></span><span style="line-height: 26px;"><span leaf="">(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> Exception </span></span><span leaf="">{</span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">default</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">afterCompletion</span></span><span style="line-height: 26px;"><span leaf="">(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> Exception </span></span><span leaf="">{</span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">接口注释意思大致是说,</span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">HandlerInterceptor</span></code><span leaf=""> 是在通过 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">HandlerAdapter</span></code><span leaf=""> 执行查找到的 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">handler</span></code><span leaf=""> 之前被调用,这种机制主要目的是为了减少重复代码,用于大量的程序预处理工作,比如授权检查等。</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">preHandle方法</span></code><span leaf="">:在 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">controller</span></code><span leaf=""> 方法调用之前,按照 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Interceptor</span></code><span leaf=""> 链</span><strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">顺序执行</span></strong><span leaf="">,进行权限检查等请求前处理操作。</span> <blockquote style="margin-top: 20px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;padding-top: 10px;padding-bottom: 10px;padding-left: 20px;padding-right: 10px;border-top-style: none;border-bottom-style: none;border-left-style: solid;border-right-style: solid;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 1px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgb(150, 84, 181);border-right-color: rgb(150, 84, 181);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;background-attachment: scroll;background-clip: border-box;background-color: rgb(251, 249, 253);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;display: block;overflow-x: auto;overflow-y: auto;"> <span style="display: none;color: rgb(0, 0, 0);font-size: 16px;line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: normal;"></span> <p style="text-indent: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0px;margin-left: 0px;"><span leaf="">如果该方法返回了 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">false</span></code><span leaf="">,那么不仅当前 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;height: auto;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Interceptor</span></code><span leaf=""> 会终止执行,整个拦截器链都会被终止。</span></p> </blockquote> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">postHandle方法</span></code><span leaf="">:在 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">controller</span></code><span leaf=""> 方法调用之后返回 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">ModelAndView</span></code><span leaf=""> 之前执行,与 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">preHandle</span></code><span leaf=""> 不同的是,</span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">postHandle</span></code><span leaf=""> 是按照</span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Interceptor</span></code><span leaf=""> 链</span><strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">逆序执行</span></strong><span leaf="">的。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">afterCompletion方法</span></code><span leaf="">:在整个请求完成后调用,通常用于资源清理或日志记录。</span> </section></li> </ul> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">执行顺序:</span></strong><span leaf=""><img class="rich_pages wxw-img" data-imgfileid="100003274" src="/upload/f35b1a3bf81f30cdc9cfb98e05b73b18.png" data-type="png" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;"></span></p> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">下面我们通过 Spring MVC 在实际分发处理请求时的源码具体看下 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Interceptor</span></code><span leaf=""> 的执行情况(源码出自 spring-framework-5.0.x):</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg k0ue4mipav882cnbmffjvlrxfiaoyowabg1n9gndbfbyylu3av0epdc78k5wnsukhhozztyffw9mdqxuoquchp80rlmqpmiibl 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">protected</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">doDispatch</span></span><span style="line-height: 26px;"><span leaf="">(HttpServletRequest request, HttpServletResponse response)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> Exceptio </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 此处用 processedRequest 接收了用户的 request 请求</span></span><br><span leaf=""> HttpServletRequest processedRequest = request;</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// HandlerExecutionChain 局部变量</span></span><br><span leaf=""> HandlerExecutionChain mappedHandler = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">null</span></span><span leaf="">;</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 标记一下是否解析了文件类型的数据,如果有最终需要清理操作</span></span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">boolean</span></span><span leaf=""> multipartRequestParsed = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">false</span></span><span leaf="">;</span><br><br><span leaf=""> WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);</span><br><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">try</span></span><span leaf=""> {</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// ModelAndView 局部变量</span></span><br><span leaf=""> ModelAndView mv = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">null</span></span><span leaf="">;</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 处理异常局部变量</span></span><br><span leaf=""> Exception dispatchException = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">null</span></span><span leaf="">;</span><br><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">try</span></span><span leaf=""> {</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">/**</span><br><span leaf=""> * 判断一下是否是文件上传请求。</span><br><span leaf=""> * 如果请求是 POST 请求,并且 Context-Type 是以 multipart/ 开头的就认为是文件上传的请求。</span><br><span leaf=""> * 需要注意的是,若是这里被认定为文件上传请求,processedRequest 和 request 将不再指向同一对象</span><br><span leaf=""> * 这里返回的是 MultipartHttpServletRequest。</span><br><span leaf=""> */</span></span><br><span leaf=""> processedRequest = checkMultipart(request);</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 两个请求不再相同,进行文件上传标记,用于后续清理操作</span></span><br><span leaf=""> multipartRequestParsed = (processedRequest != request);</span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">/**</span><br><span leaf=""> * 向 HandlerMapping 请求查找 HandlerExecutionChain</span><br><span leaf=""> * 找到一个处理器,如果没有找到对应的处理类的话,这里通常会返回404。</span><br><span leaf=""> */</span></span><br><span leaf=""> mappedHandler = getHandler(processedRequest);</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 如果没找到对应的处理器,则抛出异常</span></span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 相信大家都见过 'No mapping for GET /xxxx',就是这里抛出的</span></span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> (mappedHandler == </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">null</span></span><span leaf="">) {</span><br><span leaf=""> noHandlerFound(processedRequest, response);</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf="">;</span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 根据查找到的 Handler 请求查找能够进行处理的 HandlerAdapter</span></span><br><span leaf=""> HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());</span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 判断自上次请求后是否有修改,没有修改直接返回响应</span></span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 如果是GET请求,且内容没有变化的话,就直接返回</span></span><br><span leaf=""> String method = request.getMethod();</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">boolean</span></span><span leaf=""> isGet = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"GET"</span></span><span leaf="">.equals(method);</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> (isGet || </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"HEAD"</span></span><span leaf="">.equals(method)) {</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">long</span></span><span leaf=""> lastModified = ha.getLastModified(request, mappedHandler.getHandler());</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> (log.isDebugEnabled()) {</span><br><span leaf=""> log.debug(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Last-Modified value for ["</span></span><span leaf=""> + getRequestUri(request) + </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"] is: "</span></span><span leaf=""> + lastModified);</span><br><span leaf=""> }</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> (</span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf="">;</span><br><span leaf=""> }</span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">/**</span><br><span leaf=""> * <<<<<<<<<这里到了我们本节内容,拦截器的执行了>>>>>>>>></span><br><span leaf=""> * 这里通过 applyPreHandle 方法,按顺序依次执行 HandlerInterceptor 的 preHandle 方法</span><br><span leaf=""> * 可以看到,如果任一 HandlerInterceptor 的 preHandle 方法返回了 false, 则整个拦截器连</span><br><span leaf=""> * 不再继续进行处理。</span><br><span leaf=""> */</span></span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> (!mappedHandler.applyPreHandle(processedRequest, response)) {</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf="">;</span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">/**</span><br><span leaf=""> * 通过 HandlerAdapter 执行查找到的 handler</span><br><span leaf=""> * 这里真正执行我们 controller 中的方法逻辑,返回一个 ModelAndView</span><br><span leaf=""> */</span></span><br><span leaf=""> mv = ha.handle(processedRequest, response, mappedHandler.getHandler());</span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">/**</span><br><span leaf=""> * 检查是否已经开始处理并发请求,如果并发处理已经开始,那么当前的请求线程就可以返回了,而不会等待异步操 * 作的结果,也就不会再执行拦截器 PostHandle 之类的操作了。</span><br><span leaf=""> */</span></span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> (asyncManager.isConcurrentHandlingStarted()) {</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf="">;</span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 如果我们没有设置 viewName,就采用默认的,否则采用我们自己的</span></span><br><span leaf=""> applyDefaultViewName(processedRequest, mv);</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// <<<<<<<<< 这里,通过 applyPostHandle 逆序执行 HandlerInterceptor 的 postHandle 方法>>>>>>>>></span></span><br><span leaf=""> mappedHandler.applyPostHandle(processedRequest, response, mv);</span><br><span leaf=""> }</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">catch</span></span><span leaf=""> (Exception ex) {</span><br><span leaf=""> dispatchException = ex;</span><br><span leaf=""> }</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">catch</span></span><span leaf=""> (Throwable err) {</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// As of 4.3, we're processing Errors thrown from handler methods as well,</span></span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// making them available for @ExceptionHandler methods and other scenarios.</span></span><br><span leaf=""> dispatchException = </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> NestedServletException(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Handler dispatch failed"</span></span><span leaf="">, err);</span><br><span leaf=""> }</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 渲染视图填充 Model,如果有异常渲染异常页面</span></span><br><span leaf=""> processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);</span><br><span leaf=""> }</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">catch</span></span><span leaf=""> (Exception ex) {</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 如果有异常按倒序执行所有 HandlerInterceptor 的 afterCompletion 方法</span></span><br><span leaf=""> triggerAfterCompletion(processedRequest, response, mappedHandler, ex);</span><br><span leaf=""> }</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">catch</span></span><span leaf=""> (Throwable err) {</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 如果有异常按倒序执行所有 HandlerInterceptor 的 afterCompletion 方法</span></span><br><span leaf=""> triggerAfterCompletion(processedRequest, response, mappedHandler,</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> NestedServletException(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Handler processing failed"</span></span><span leaf="">, err));</span><br><span leaf=""> }</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">finally</span></span><span leaf=""> {</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> (asyncManager.isConcurrentHandlingStarted()) {</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// Instead of postHandle and afterCompletion</span></span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> (mappedHandler != </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">null</span></span><span leaf="">) {</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 倒序执行所有 HandlerInterceptor 的 afterCompletion 方法</span></span><br><span leaf=""> mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);</span><br><span leaf=""> }</span><br><span leaf=""> }</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">else</span></span><span leaf=""> {</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// Clean up any resources used by a multipart request.</span></span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> (multipartRequestParsed) {</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 如果请求包含文件类型的数据则进行相关清理工作</span></span><br><span leaf=""> cleanupMultipart(processedRequest);</span><br><span leaf=""> }</span><br><span leaf=""> }</span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">上述源码中,其实不仅仅是拦截器的执行顺序了,而是 Spring MVC 处理客户端请求的整个过程。如下图,可以很直观的看出拦截器的执行时机与顺序。</span></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img class="rich_pages wxw-img" data-imgfileid="100003276" src="/upload/2453abb72c876e15ed9de83ddccc013d.jpg" data-type="jpeg" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"></span> <figcaption style="color: rgb(136, 136, 136);font-size: 14px;line-height: 1.5em;letter-spacing: 0em;text-align: center;font-weight: normal;margin-top: 5px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"> <span leaf="">图片来源于网络,侵权请联系删除</span> </figcaption> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;"><span leaf="">Interceptor 的配置使用</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">自定义拦截器,实现 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">HandlerInterceptor</span></code><span leaf=""> 接口</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg k0ue4mipav882cnbmffjvlrxfiaoyowabg1n9gndbfbyylu3av0epdc78k5wnsukhhozztyffw9mdqxuoquchp80rlmqpmiibl 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">MyInterceptor</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">implements</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">HandlerInterceptor</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">boolean</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">preHandle</span></span><span style="line-height: 26px;"><span leaf="">(HttpServletRequest request, HttpServletResponse response, Object handler)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> Exception </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 在这里添加拦截逻辑,例如身份验证或日志记录</span></span><br><span leaf=""> System.out.println(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"MyInterceptor preHandle: "</span></span><span leaf=""> + request.getRequestURI());</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">true</span></span><span leaf="">; </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 返回 true 继续处理请求,返回 false 中断请求</span></span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">postHandle</span></span><span style="line-height: 26px;"><span leaf="">(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> Exception </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 在视图渲染之前执行的逻辑</span></span><br><span leaf=""> System.out.println(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"MyInterceptor postHandle: "</span></span><span leaf=""> + request.getRequestURI());</span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">afterCompletion</span></span><span style="line-height: 26px;"><span leaf="">(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> Exception </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 请求完成后的逻辑,比如资源清理</span></span><br><span leaf=""> System.out.println(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"MyInterceptor afterCompletion: "</span></span><span leaf=""> + request.getRequestURI());</span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">实现 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">WebMvcConfigurer</span></code><span leaf=""> 接口并重写 </span><code style="color: rgb(150, 84, 181);font-size: 14px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">addInterceptors</span></code><span leaf=""> 方法,将拦截器注册到 Spring MVC 的拦截器链中</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg k0ue4mipav882cnbmffjvlrxfiaoyowabg1n9gndbfbyylu3av0epdc78k5wnsukhhozztyffw9mdqxuoquchp80rlmqpmiibl 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Configuration</span></span><br><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">WebConfig</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">implements</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">WebMvcConfigurer</span></span><span leaf=""> </span></span><span leaf="">{</span><br><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Override</span></span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">addInterceptors</span></span><span style="line-height: 26px;"><span leaf="">(InterceptorRegistry registry)</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 添加拦截器,并指定拦截路径模式</span></span><br><span leaf=""> registry.addInterceptor(</span><span style="color: #c678dd;line-height: 26px;"><span leaf="">new</span></span><span leaf=""> MyInterceptor())</span><br><span leaf=""> .addPathPatterns(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"/**"</span></span><span leaf="">) </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 拦截所有路径</span></span><br><span leaf=""> .excludePathPatterns(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"/static/**"</span></span><span leaf="">, </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"/login"</span></span><span leaf="">, </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"/register"</span></span><span leaf="">); </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 排除静态资源和某些 URL</span></span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <h2 data-tool="mdnice编辑器" style=" margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset; text-align: left;text-shadow: none;transform: none;width: 100%;-webkit-box-reflect: unset; "><span style="display: none;"></span><span style=" font-size: 22px;border-bottom-color: rgb(119, 48, 152);color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: 85%;height: auto;align-items: unset;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 10px;padding-left: 0px;padding-right: 0px; text-align: center;text-indent: 0em;text-shadow: none;transform: none;-webkit-box-reflect: unset; "><span leaf="">AOP(Aspect-Oriented Programming)</span></span><span style="display: none;"></span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;"><span leaf="">什么是 AOP</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">AOP(Aspect-Oriented Programming),即面向切面编程,是一种编程范式,目的是通过分离横切关注点(如事务管理、日志记录)来提高代码的模块化程度。AOP 允许开发者定义“切面”(Aspects),通过这些切面可以在不改变业务逻辑的情况下增强现有业务功能。</span></p> <blockquote style="margin-top: 20px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;padding-top: 10px;padding-bottom: 10px;padding-left: 20px;padding-right: 10px;border-top-style: none;border-bottom-style: none;border-left-style: solid;border-right-style: solid;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 1px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgb(150, 84, 181);border-right-color: rgb(150, 84, 181);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;background-attachment: scroll;background-clip: border-box;background-color: rgb(251, 249, 253);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;display: block;overflow-x: auto;overflow-y: auto;"> <span style="display: none;color: rgb(0, 0, 0);font-size: 16px;line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: normal;"></span> <p style="text-indent: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0px;margin-left: 0px;"><span leaf="">AOP 是一种编程思想,Spring AOP 是 Spring 框架提供的 AOP 实现。</span></p> </blockquote> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;"><span leaf="">AOP 核心概念</span></span><span style="display: none;"></span></h3> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">切面(Aspect)</span></strong><span leaf="">:一个模块化的特殊类,包含通知和切入点,用来实现特定的横切逻辑。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">通知(Advice)</span></strong><span leaf="">:在特定连接点(Join Point)执行的动作,例如前置通知(在目标方法调用之前执行的通知)。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">连接点(Join Point)</span></strong><span leaf="">:程程序执行过程中的一个点,例如方法调用或异常抛出的地方。在 Spring AOP 中,连接点指的是应用程序中所有可能被拦截的方法执行点。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">切入点(Pointcut)</span></strong><span leaf="">:用于匹配连接点的表达式,决定了哪些连接点会应用切面的通知。Spring AOP 使用 AspectJ 的切入点表达式语言。例如:</span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">@Pointcut("execution(* com.example.service..*.*(..))")</span></code> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">引入(Introduction)</span></strong><span leaf="">:为现有的类添加新方法或属性的能力。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">目标对象(Target Object)</span></strong><span leaf="">:目标对象是指被一个或多个切面所通知的对象,也就是需要对其方法调用进行增强的对象。使用 AOP 时,这些对象会被代理,以便可以在它们的方法调用前后插入额外的行为。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">代理(Proxy)</span></strong><span leaf="">:由 AOP 框架创建的对象,用来实现对目标对象的增强。有两种主要类型的 AOP 代理:JDK 动态代理和 CGLIB 代理。</span> </section></li> </ul> <blockquote style="margin-top: 20px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;padding-top: 10px;padding-bottom: 10px;padding-left: 20px;padding-right: 10px;border-top-style: none;border-bottom-style: none;border-left-style: solid;border-right-style: solid;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 1px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgb(150, 84, 181);border-right-color: rgb(150, 84, 181);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;background-attachment: scroll;background-clip: border-box;background-color: rgb(251, 249, 253);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;display: block;overflow-x: auto;overflow-y: auto;"> <span style="display: none;color: rgb(0, 0, 0);font-size: 16px;line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: normal;"></span> <p style="text-indent: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0px;margin-left: 0px;"><span leaf="">Spring AOP 如何创建代理:</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">默认情况下,如果目标对象实现了至少一个接口,Spring AOP 将优先选择 JDK 动态代理。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">如果目标对象没有实现任何接口,则会自动切换到 CGLIB 代理。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">如果要强制使用 CGLIB 代理,可以在启动类或配置类上添加 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">@EnableAspectJAutoProxy(proxyTargetClass = true)</span></code><span leaf=""> 注解即可。</span> </section></li> </ul> </blockquote> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;"><span leaf="">Spring AOP 的配置使用</span></span><span style="display: none;"></span></h3> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: block;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(0, 0, 0);line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: bold;display: block;"><span leaf="">Spring AOP 的使用步骤</span></span><span style="display: none;"></span></h4> <ol style="list-style-type: decimal;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">启用 AOP 支持</span></strong><span leaf="">:在启动类或任意配置类上添加 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">@EnableAspectJAutoProxy</span></code><span leaf=""> 注解。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">定义切面(Aspect)</span></strong><span leaf="">:创建一个类,使用 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">@Aspect</span></code><span leaf=""> 注解来标记这个类为一个切面,并使用 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">@Component</span></code><span leaf=""> 注解让 Spring 管理这个 Bean。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">指定切入点(Pointcut)</span></strong><span leaf="">:使用 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">@Pointcut</span></code><span leaf=""> 注解加 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">AspectJ</span></code><span leaf=""> 表达式定义切入点。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">定义通知(Advice)</span></strong><span leaf="">:定义一个通知,在特定连接点时执行特定逻辑。</span> </section></li> </ol> <blockquote style="margin-top: 20px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;padding-top: 10px;padding-bottom: 10px;padding-left: 20px;padding-right: 10px;border-top-style: none;border-bottom-style: none;border-left-style: solid;border-right-style: solid;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 1px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgb(150, 84, 181);border-right-color: rgb(150, 84, 181);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;background-attachment: scroll;background-clip: border-box;background-color: rgb(251, 249, 253);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;display: block;overflow-x: auto;overflow-y: auto;"> <span style="display: none;color: rgb(0, 0, 0);font-size: 16px;line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: normal;"></span> <p style="text-indent: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0px;margin-left: 0px;"><span leaf="">Spring 提供的通知类型有如下几种:</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">@Before(前置通知)</span></strong><span leaf="">:前置通知是在目标方法调用 </span><strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">之前</span></strong><span leaf=""> 执行的通知。无论目标方法是否抛出异常或正常返回,前置通知都会被执行。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">@AfterReturning(后置返回通知)</span></strong><span leaf="">:后置返回通知是在目标方法 </span><strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">成功返回后</span></strong><span leaf=""> 执行的通知。只有当目标方法没有抛出异常时,才会触发该通知。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">@AfterThrowing(抛出异常通知)</span></strong><span leaf="">:抛出异常通知是在目标方法 </span><strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">抛出异常后</span></strong><span leaf=""> 执行的通知。它只会在方法抛出指定类型的异常时触发。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">@Around(环绕通知)</span></strong><span leaf="">:环绕通知是最强大的一种通知类型,它包围了目标方法的调用。你可以完全控制方法的执行,包括决定是否继续执行方法以及如何处理返回值或异常。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">@After(后置最终通知)</span></strong><span leaf="">:后置最终通知是在目标方法 </span><strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">完成之后</span></strong><span leaf=""> 执行的通知,不论方法是正常结束还是因为异常而终止。</span> </section></li> </ul> </blockquote> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: block;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(0, 0, 0);line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: bold;display: block;"><span leaf="">Spring AOP 使用示例</span></span><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">启用 AOP 支持</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg k0ue4mipav882cnbmffjvlrxfiaoyowabg1n9gndbfbyylu3av0epdc78k5wnsukhhozztyffw9mdqxuoquchp80rlmqpmiibl 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;"><span leaf="">@SpringBootApplication</span></span><br><span style="color: #61aeee;line-height: 26px;"><span leaf="">@EnableAspectJAutoProxy</span></span><br><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">MyApp</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">static</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">main</span></span><span style="line-height: 26px;"><span leaf="">(String[] args)</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> SpringApplication.run(MyApp</span><span style="line-height: 26px;"><span leaf="">.</span><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf="">, </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">args</span></span><span leaf="">)</span></span><span leaf="">;</span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">定义切面类</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg k0ue4mipav882cnbmffjvlrxfiaoyowabg1n9gndbfbyylu3av0epdc78k5wnsukhhozztyffw9mdqxuoquchp80rlmqpmiibl 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Slf</span></span><span leaf="">4j</span><br><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Aspect</span></span><br><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Component</span></span><br><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">AllAdviceAspect</span></span><span leaf=""> </span></span><span leaf="">{</span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 定义切入点,匹配 service 包下的所有方法</span></span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Pointcut</span></span><span leaf="">(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"execution(* com.example.service..*.*(..))"</span></span><span leaf="">)</span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">serviceLayerExecution</span></span><span style="line-height: 26px;"><span leaf="">()</span></span><span leaf=""> </span></span><span leaf="">{}</span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 前置通知,在方法调用前打印日志</span></span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Before</span></span><span leaf="">(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"serviceLayerExecution()"</span></span><span leaf="">)</span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">logBefore</span></span><span style="line-height: 26px;"><span leaf="">(JoinPoint joinPoint)</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> log.info(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Before method execution: {}"</span></span><span leaf="">, joinPoint.getSignature().getName());</span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 后置返回通知,在方法成功返回后打印日志</span></span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@AfterReturning</span></span><span leaf="">(pointcut = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"serviceLayerExecution()"</span></span><span leaf="">, returning = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"result"</span></span><span leaf="">)</span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">logAfterReturning</span></span><span style="line-height: 26px;"><span leaf="">(JoinPoint joinPoint, Object result)</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> log.info(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Method returned successfully: {}, Result: {}"</span></span><span leaf="">, joinPoint.getSignature().getName(), result);</span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 抛出异常通知,在方法抛出异常后打印日志</span></span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@AfterThrowing</span></span><span leaf="">(pointcut = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"serviceLayerExecution()"</span></span><span leaf="">, throwing = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"ex"</span></span><span leaf="">)</span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">logAfterThrowing</span></span><span style="line-height: 26px;"><span leaf="">(JoinPoint joinPoint, Exception ex)</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> log.error(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"An exception was thrown in {}: {}"</span></span><span leaf="">, joinPoint.getSignature().getName(), ex.getMessage());</span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 后置最终通知,在方法完成之后打印日志,无论是否抛出异常</span></span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@After</span></span><span leaf="">(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"serviceLayerExecution()"</span></span><span leaf="">)</span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">void</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">logAfter</span></span><span style="line-height: 26px;"><span leaf="">(JoinPoint joinPoint)</span></span><span leaf=""> </span></span><span leaf="">{</span><br><span leaf=""> log.info(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"After method execution: {}"</span></span><span leaf="">, joinPoint.getSignature().getName());</span><br><span leaf=""> }</span><br><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 环绕通知,包围方法调用,控制方法执行流程</span></span><br><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">@Around</span></span><span leaf="">(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"serviceLayerExecution()"</span></span><span leaf="">)</span><br><span leaf=""> </span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">public</span></span><span leaf=""> Object </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">logAround</span></span><span style="line-height: 26px;"><span leaf="">(ProceedingJoinPoint pjp)</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throws</span></span><span leaf=""> Throwable </span></span><span leaf="">{</span><br><span leaf=""> log.info(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Starting around advice for method: {}"</span></span><span leaf="">, pjp.getSignature().getName());</span><br><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">long</span></span><span leaf=""> start = System.currentTimeMillis();</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">try</span></span><span leaf=""> {</span><br><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 执行目标方法</span></span><br><span leaf=""> Object result = pjp.proceed();</span><br><span leaf=""> log.info(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Method {} took {} ms to execute"</span></span><span leaf="">, pjp.getSignature().getName(), System.currentTimeMillis() - start);</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> result;</span><br><span leaf=""> } </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">catch</span></span><span leaf=""> (Throwable e) {</span><br><span leaf=""> log.error(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Error during method execution: {}"</span></span><span leaf="">, e.getMessage());</span><br><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">throw</span></span><span leaf=""> e; </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf="">// 重新抛出异常以便后续处理</span></span><br><span leaf=""> } </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">finally</span></span><span leaf=""> {</span><br><span leaf=""> log.info(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Ending around advice for method: {}"</span></span><span leaf="">, pjp.getSignature().getName());</span><br><span leaf=""> }</span><br><span leaf=""> }</span><br><span leaf="">}</span><br></code></pre> <h2 data-tool="mdnice编辑器" style=" margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset; text-align: left;text-shadow: none;transform: none;width: 100%;-webkit-box-reflect: unset; "><span style="display: none;"></span><span style=" font-size: 22px;border-bottom-color: rgb(119, 48, 152);color: rgb(119, 48, 152);line-height: 1.5em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: 85%;height: auto;align-items: unset;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 10px;padding-left: 0px;padding-right: 0px; text-align: center;text-indent: 0em;text-shadow: none;transform: none;-webkit-box-reflect: unset; "><span leaf="">三者之间对比</span></span><span style="display: none;"></span></h2> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Filter</span></code><span leaf=""> 是 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Java Servlet</span></code><span leaf=""> 规范的一部分,它工作在 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Servlet</span></code><span leaf=""> 容器层面,是 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Servlet</span></code><span leaf=""> 容器级别的,适用于所有进入应用的 HTTP 请求。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Interceptor</span></code><span leaf=""> 是 Spring MVC 框架提供的一种请求处理机制,是属于框架级别的。通过 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Interceptor</span></code><span leaf=""> 章节的源码可以看出,</span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Interceptor</span></code><span leaf=""> 工作在 Spring MVC 分发处理请求时,而分发请求的类是 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">DispatcherServlet</span></code><span leaf="">,它是一个 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Servlet</span></code><span leaf="">,根据 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Servlet</span></code><span leaf=""> 规范,</span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Filter</span></code><span leaf=""> 是先于 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Servlet</span></code><span leaf=""> 执行的。所以 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Filter</span></code><span leaf=""> 要比 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Interceptor</span></code><span leaf=""> 优先执行。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">Spring AOP 是 Spring 框架提供的面向切面编程的支持,允许我们在不改变原有业务逻辑的前提下,集中处理横切关注点。它的执行时机是在特定的连接点,也就是请求已经到了我们 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">controller</span></code><span leaf=""> 中的某个方法时才会触发,而 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Interceptor</span></code><span leaf=""> 在执行查找到的 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">handler</span></code><span leaf=""> 之前就已经被调用了,所以 </span><code style="background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Interceptor</span></code><span leaf=""> 要先于 Spring AOP 执行。</span> </section></li> </ul> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">执行顺序如下图:</span></strong></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img class="rich_pages wxw-img" data-imgfileid="100003275" src="/upload/b3d9b349c7e734c17c83705218cc47a9.png" data-type="png" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">本篇主要基于 SpringBoot 介绍了过滤器、拦截器和 Spring AOP,通过学习其基本知识了解到了它们工作时的执行顺序。实际上,其实无论是过滤器还是拦截器,都可以被视为 AOP 思想的具体实现形式,尽管它们各自工作在不同的层次上。</span></p> <p data-tool="mdnice编辑器" style="color: rgb(90, 90, 90);font-size: 15px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">您的鼓励对我持续创作非常关键,如果本文对您有帮助,请记得</span><strong style="color: rgb(0, 0, 0);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">点赞、分享、在看</span></strong><span leaf="">哦~~~谢谢!</span></p> </section> <p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p>
作者:微信小助手
<section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">结论:</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;"> </span><span textstyle="" style="font-size: 16px;font-style: italic;text-decoration: underline;">解析同步效率:</span><span textstyle="" style="font-size: 16px;color: rgb(255, 76, 0);font-weight: bold;font-style: italic;text-decoration: underline;">Flinkcdc完胜 (遥遥领先!!!!!)</span></span> </section> <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=""><code><span leaf=""><span class="code-snippet__plaintext"> Flinkcdc > Canal</span></span></code></pre> </section> <section> <span leaf=""> 选择用哪个?</span> </section> <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=""><code><span leaf=""><span class="code-snippet__plaintext">推荐:Flinkcdc</span></span></code></pre> </section> <section> <span leaf=""><br></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">一、测试对比:</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">1.1、版本对比:</span></span> </section> <section> <code><span leaf="" data-pm-slice="1 1 [" codeblock,{data-lang:xml},code,{}]><span textstyle="" style="font-size: 16px;font-weight: bold;">1、Flinkcdc</span></span></code> </section> <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 leaf=""><span class="code-snippet__tag"><span class="code-snippet__plaintext"><</span></span><span class="code-snippet__tag"><span class="code-snippet__name">dependency</span></span><span class="code-snippet__tag"><span class="code-snippet__plaintext">></span></span><span class="code-snippet__plaintext"> </span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__tag"><span class="code-snippet__plaintext"><</span></span><span class="code-snippet__tag"><span class="code-snippet__name">groupId</span></span><span class="code-snippet__tag"><span class="code-snippet__plaintext">></span></span><span class="code-snippet__plaintext">com.ververica</span><span class="code-snippet__tag"><span class="code-snippet__plaintext"><!--/</span--></span><span class="code-snippet__tag"><span class="code-snippet__name">groupId</span></span><span class="code-snippet__tag"><span class="code-snippet__plaintext">></span></span><span class="code-snippet__plaintext"> </span></span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__tag"><span class="code-snippet__plaintext"><</span></span><span class="code-snippet__tag"><span class="code-snippet__name">artifactId</span></span><span class="code-snippet__tag"><span class="code-snippet__plaintext">></span></span><span class="code-snippet__plaintext">flink-connector-mysql-cdc</span><span class="code-snippet__tag"><span class="code-snippet__plaintext"><!--/</span--></span><span class="code-snippet__tag"><span class="code-snippet__name">artifactId</span></span><span class="code-snippet__tag"><span class="code-snippet__plaintext">></span></span><span class="code-snippet__plaintext"> </span></span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__tag"><span class="code-snippet__plaintext"><</span></span><span class="code-snippet__tag"><span class="code-snippet__name">version</span></span><span class="code-snippet__tag"><span class="code-snippet__plaintext">></span></span><span class="code-snippet__plaintext">2.4.0</span><span class="code-snippet__tag"><span class="code-snippet__plaintext"><!--/</span--></span><span class="code-snippet__tag"><span class="code-snippet__name">version</span></span><span class="code-snippet__tag"><span class="code-snippet__plaintext">></span></span></span></span></code><code><span leaf=""><span class="code-snippet__tag"><span class="code-snippet__plaintext"><!--/</span--></span><span class="code-snippet__tag"><span class="code-snippet__name">dependency</span></span><span class="code-snippet__tag"><span class="code-snippet__plaintext">></span></span></span></span></code></pre> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">2、canal:</span></span> </section> <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=""><code><span leaf=""><span class="code-snippet__plaintext">canal.deployer-1.1.5.tar.gz</span></span></code></pre> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">1.2、数据总量:</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: normal;"> 在MySQL数据库中导入</span><span textstyle="" style="font-size: 16px;color: rgb(255, 0, 0);font-weight: bold;font-style: italic;text-decoration: underline;">数据量为 1.5亿数据(涉及200多个表),4个小时导入完成</span><span textstyle="" style="font-size: 16px;font-weight: normal;">。Flinkcdc和Canal都什么时候同步完成了?</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;color: rgb(255, 0, 0);font-style: italic;text-decoration: underline;">注:Flinkcdc 和Canal同时接入同一个库来数据解析并同步数据。</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;color: rgb(255, 0, 0);font-weight: bold;font-style: italic;text-decoration: underline;">前提条件:</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;color: rgb(0, 82, 255);font-style: italic;text-decoration: underline;">数据:1.5亿</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;color: rgb(0, 82, 255);font-style: italic;text-decoration: underline;">导入时长:4个小时</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">1、Flinkcdc:</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;">解析同步时长:</span><span textstyle="" style="font-size: 16px;color: rgb(255, 76, 0);font-weight: bold;">6个小时</span></span> </section> <section style="text-align: center;" nodeleaf=""> <img class="rich_pages wxw-img" data-imgfileid="100001548" data-ratio="0.2644281217208814" data-s="300,640" src="/upload/ad62b4b758fdf6057dc80640c3f9439f.png" data-type="png" data-w="953" type="block"> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">2、Canal:</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;">解析同步时长:</span><span textstyle="" style="font-size: 16px;color: rgb(255, 76, 0);font-weight: bold;">13个小时</span></span> </section> <section style="text-align: center;" nodeleaf=""> <img class="rich_pages wxw-img" data-imgfileid="100001549" data-ratio="0.24310520939734423" data-s="300,640" src="/upload/2af47fa04c74e7642b1d642e84339e25.png" data-type="png" data-w="979" type="block"> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">结论:</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;"> 解析同步效率:</span><span class="code-snippet__plaintext">Flinkcdc </span><span textstyle="" style="font-size: 16px;color: rgb(255, 76, 0);font-style: italic;text-decoration: underline;">完胜</span></span> </section> <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=""><code><span leaf=""><span class="code-snippet__plaintext"> Flinkcdc > Canal</span></span></code></pre> </section> <section> <span leaf=""><br></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">1.3、如果现有Canal需升级为Flinkcdc?怎么弄了?(</span><span textstyle="" style="font-size: 18px;color: rgb(255, 0, 0);font-weight: bold;">生产环境</span><span textstyle="" style="font-size: 16px;font-weight: bold;">)</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">结论:</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">1、数据格式转换:</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;"> </span><span textstyle="" style="font-size: 16px;color: rgb(0, 82, 255);font-style: italic;text-decoration: underline;">将Flinkcdc的数据格式转换成Canal数据格式。其余都不用变。</span></span> </section> <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=""><code><span leaf=""><span class="code-snippet__plaintext"> FlinkCdcEvent -> CanalEvent</span></span></code></pre> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">2、数据解析后都是Json:</span></span> </section> <section> <span leaf=""><br></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 18px;color: rgb(255, 0, 0);font-weight: bold;"> </span><span textstyle="" style="font-size: 18px;color: rgb(255, 0, 0);font-weight: bold;font-style: italic;text-decoration: underline;">记得用Gson转换。fastjson有坑,不建议用.</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 18px;color: rgb(255, 0, 0);font-weight: bold;"> </span><span textstyle="" style="font-size: 18px;color: rgb(255, 0, 0);font-weight: bold;font-style: italic;text-decoration: underline;"> 记得用Gson转换。fastjson有坑,不建议用.</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 18px;color: rgb(255, 0, 0);font-weight: bold;"> </span><span textstyle="" style="font-size: 18px;color: rgb(255, 0, 0);font-weight: bold;font-style: italic;text-decoration: underline;"> 记得用Gson转换。fastjson有坑,不建议用.</span></span> </section> <section> <span leaf=""><br></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">1.4、Flinkcdc及Canal数据格式对比:</span></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">1、CanalEvent:</span></span> </section> <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="typescript"><code><span leaf=""><span class="code-snippet__keyword">import</span><span class="code-snippet__plaintext"> java.</span><span class="code-snippet__property">util</span><span class="code-snippet__plaintext">.</span><span class="code-snippet__property">List</span><span class="code-snippet__plaintext">;</span></span></code><code><span leaf=""><span class="code-snippet__keyword">import</span><span class="code-snippet__plaintext"> java.</span><span class="code-snippet__property">util</span><span class="code-snippet__plaintext">.</span><span class="code-snippet__property">Map</span><span class="code-snippet__plaintext">;</span></span></code><code><span leaf=""><span class="code-snippet__keyword">public</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">class</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">CanalEvent</span><span class="code-snippet__plaintext"> {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">List</span><span class="code-snippet__plaintext"><</span><span class="code-snippet__title">Map</span><span class="code-snippet__plaintext"><</span><span class="code-snippet__title">String</span><span class="code-snippet__plaintext">, </span><span class="code-snippet__title">String</span><span class="code-snippet__plaintext">>> data;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">String</span><span class="code-snippet__plaintext"> database;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> long es;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> long id;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__built_in">boolean</span><span class="code-snippet__plaintext"> isDdl;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">Map</span><span class="code-snippet__plaintext"><</span><span class="code-snippet__title">String</span><span class="code-snippet__plaintext">, </span><span class="code-snippet__title">String</span><span class="code-snippet__plaintext">> mysqlType;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">List</span><span class="code-snippet__plaintext"><</span><span class="code-snippet__title">Map</span><span class="code-snippet__plaintext"><</span><span class="code-snippet__title">String</span><span class="code-snippet__plaintext">, </span><span class="code-snippet__title">String</span><span class="code-snippet__plaintext">>> old;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">List</span><span class="code-snippet__plaintext"><</span><span class="code-snippet__title">String</span><span class="code-snippet__plaintext">> pkNames;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">String</span><span class="code-snippet__plaintext"> sql;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">Map</span><span class="code-snippet__plaintext"><</span><span class="code-snippet__title">String</span><span class="code-snippet__plaintext">, </span><span class="code-snippet__title">Integer</span><span class="code-snippet__plaintext">> sqlType;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">String</span><span class="code-snippet__plaintext"> table;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> long ts;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">private</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__title">String</span><span class="code-snippet__plaintext"> </span><span class="code-snippet__keyword">type</span><span class="code-snippet__plaintext">;</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__comment">// Getters and setters</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> // toString</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> ...</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">}</span></span></code></pre> </section> <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="javascript"><code><span leaf=""><span class="code-snippet__plaintext">{</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"data"</span><span class="code-snippet__plaintext">: [</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"G00002"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"阿龙大数据"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"province_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"32"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"province"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"江苏省"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"city_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"3201"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"city"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"南京市"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"district_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"320114"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"district"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"雨花台区"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"address"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"科创城23222333444"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"logo_url"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"http://along/icon_112.png"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"slogan"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"欢迎"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"credit_code"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"2343243"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"master_name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"阿龙"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"master_idcard"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"532524199911304246"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"power_group_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"9996"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"opt_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"2021-10-19 17:41:57"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"add_user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"132"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"add_user_name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"测试"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"add_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"2020-07-27 13:59:34"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"email"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"123456@qq.com"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"master_wechat"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"service_phone"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"13232323232"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"max_shop_num"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"5"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"pay_mode"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"business_license"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"https://image/MXVSeb7Pv4r1f1346237770562140.jpg"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"idcard_front"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"https://image/13uty9yyvrlvWb346237808202139.png"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"idcard_back"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"https:///image/5uA7IblI6r1zoW346237778042125.png"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"cloud_shop_state"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"0"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"expiration_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"version_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"company_type"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"0"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"company_property"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"1"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"main_sell"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"introduction"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"contact_name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"contact_phone"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"certification_name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"阿龙大数据"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"is_test"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"login_account"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"delete_at"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"0"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"self_invitation_code"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"IN6501"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> }</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> ],</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"database"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"test"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"es"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1669010586000</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">8150</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"isDdl"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">false</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"mysqlType"</span><span class="code-snippet__plaintext">: {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(32)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(64)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"province_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"int(6)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"province"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(32)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"city_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"int(6)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"city"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(32)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"district_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"int(6)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"district"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(64)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"address"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(128)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"logo_url"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(500)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"slogan"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(255)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"credit_code"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(18)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"master_name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(16)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"master_idcard"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(18)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"power_group_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"bigint(20)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"opt_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"datetime"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"add_user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(32)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"add_user_name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(32)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"add_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"datetime"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"email"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(255)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"master_wechat"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(255)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"service_phone"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(32)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"max_shop_num"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"int(11)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"pay_mode"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"int(1)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"business_license"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(128)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"idcard_front"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(128)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"idcard_back"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(128)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"cloud_shop_state"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"int(1)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"expiration_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"datetime"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"version_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"bigint(20)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"company_type"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"tinyint(2)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"company_property"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"int(2)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"main_sell"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(200)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"introduction"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(512)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"contact_name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(32)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"contact_phone"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(11)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"certification_name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(64)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"is_test"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"int(1)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"login_account"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"varchar(50)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"delete_at"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"bigint(14)"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"self_invitation_code"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"char(6)"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> },</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"old"</span><span class="code-snippet__plaintext">: [</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"address"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"北京"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> }</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> ],</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"pkNames"</span><span class="code-snippet__plaintext">: [</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"id"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> ],</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"sql"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">""</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"sqlType"</span><span class="code-snippet__plaintext">: {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"province_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">4</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"province"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"city_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">4</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"city"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"district_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">4</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"district"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"address"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"logo_url"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"slogan"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"credit_code"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"master_name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"master_idcard"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"power_group_id"</span><span class="code-snippet__plaintext">: -</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"opt_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">93</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"add_user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"add_user_name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"add_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">93</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"email"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"master_wechat"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"service_phone"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"max_shop_num"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">4</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"pay_mode"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">4</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"business_license"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"idcard_front"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"idcard_back"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"cloud_shop_state"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">4</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"expiration_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">93</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"version_id"</span><span class="code-snippet__plaintext">: -</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"company_type"</span><span class="code-snippet__plaintext">: -</span><span class="code-snippet__number">6</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"company_property"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">4</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"main_sell"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"introduction"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"contact_name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"contact_phone"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"certification_name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"is_test"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">4</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"login_account"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">12</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"delete_at"</span><span class="code-snippet__plaintext">: -</span><span class="code-snippet__number">5</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"self_invitation_code"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> },</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"table"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"company"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"ts"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1669010468134</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"type"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"UPDATE"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">}</span></span></code></pre> </section> <section> <span leaf=""><br></span> </section> <section> <span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">2、FlinkCdcEvent:</span></span> </section> <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="javascript"><code><span leaf=""><span class="code-snippet__plaintext">{</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"before"</span><span class="code-snippet__plaintext">: {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"PF1784570096901248"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"pay_order_no"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"out_no"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"J1784570080435328"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"title"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"充值办卡"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"from_user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"PG11111"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"from_account_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"1286009802396288"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"BO1707796995184000"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"account_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"1707895210106496"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"amount"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">13400</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"profit_state"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"profit_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1686758315000</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"refund_state"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"refund_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"add_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1686758315000</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"remark"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"充值办卡"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"acct_circle"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"PG11111"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"user_type"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">92</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"from_user_type"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">90</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"company_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"PG11111"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"profit_mode"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"type"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">2</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"parent_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"oc_profit_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"1784570096901248"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"keep_account_from_user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"keep_account_from_bm_user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"keep_account_user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"keep_account_bm_user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"biz_company_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"PG11111"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> },</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"after"</span><span class="code-snippet__plaintext">: {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"PF1784570096901248"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"pay_order_no"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"out_no"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"J1784570080435328"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"title"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"充值办卡"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"from_user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"PG11111"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"from_account_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"1286009802396288"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"BO1707796995184000"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"account_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"1707895210106496"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"amount"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">13400</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"profit_state"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"profit_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1686758315000</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"refund_state"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"refund_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"add_time"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1686758315000</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"remark"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"充值办卡1"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"acct_circle"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"PG11111"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"user_type"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">92</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"from_user_type"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">90</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"company_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"PG11111"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"profit_mode"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"type"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">2</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"parent_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"oc_profit_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"1784570096901248"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"keep_account_from_user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"keep_account_from_bm_user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"keep_account_user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"keep_account_bm_user_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"biz_company_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"PG11111"</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> },</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"source"</span><span class="code-snippet__plaintext">: {</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"version"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"1.6.4.Final"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"connector"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"mysql"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"name"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"mysql_binlog_source"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"ts_ms"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1686734882000</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"snapshot"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"false"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"db"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"cloud_test"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"sequence"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"table"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"acct_profit"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"server_id"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"gtid"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"file"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"mysql-bin.000514"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"pos"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">650576218</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"row"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">0</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"thread"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"query"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> },</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"op"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__string">"u"</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"ts_ms"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__number">1686734882689</span><span class="code-snippet__plaintext">,</span></span></code><code><span leaf=""><span class="code-snippet__plaintext"> </span><span class="code-snippet__string">"transaction"</span><span class="code-snippet__plaintext">: </span><span class="code-snippet__literal">null</span></span></code><code><span leaf=""><span class="code-snippet__plaintext">}</span></span></code></pre> </section> <section> <span leaf=""><br></span> </section> <section> <span leaf=""><br></span> </section> <section style="text-align: center;"> <span leaf=""> <span textstyle="" style="color: rgb(172, 57, 255);"> </span><span textstyle="" style="font-size: 18px;color: rgb(172, 57, 255);font-weight: bold;">记录每一份热爱,让美好永远陪伴。</span></span> </section>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-bottom: 0px;padding-left: 10px;padding-right: 10px;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;font-family: Optima, " microsoft yahei, pingfangsc-regular, serif;font-size: 16px;color: rgb(0, 0, 0);line-height: 1.5em;word-spacing: 0em;letter-spacing: 0em;word-break: break-word;text-align: left;> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"><br></p> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li><p>1 导读</p></li> <li><p>2 背景介绍</p></li> <ul style="list-style-type: square;margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li><p>2.1 为什么搭建数仓评估体系</p></li> <li><p>2.2 需要解决的技术问题</p></li> </ul> <li><p>3 设计思路</p></li> <ul style="list-style-type: square;margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li><p>3.1 整体架构设计</p></li> <li><p>3.2 产品形态设计</p></li> <li><p>3.2 指标体系搭建</p></li> </ul> <li><p>4 结果呈现</p></li> <ul style="list-style-type: square;margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li><p>4.1 结果评估模块展示</p></li> <li><p>4.2 过程评估模块展示</p></li> <li><p>4.3 阶段性治理收益</p></li> </ul> <li><p>5 未来规划</p></li> </ul> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"><br></p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 22px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">1 导读</span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 本次分享偏向于面向数仓建设、业务交付等过程中遇到的效率、质量、成本、研发等相关问题的系统性评估和治理,着重于设计思路和实践成果的展示,不涉及太多的技术细节。读者朋友可以根据自身业务场景和实际面临的问题,选择性参考并应用到实际工作中。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 22px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">2 背景介绍</span><span style="display: none;"></span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 20px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">2.1 为什么搭建数仓评估体系</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> <code style="color: rgb(255, 124, 5);line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(240, 170, 12, 0.02);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: Consolas, Monaco, Menlo, monospace;word-break: break-all;">数仓评估体系起源于23年底,作为转转数据治理的评价层,是非常重要的一环。</code>过去很长一段时间里,转转数仓团队服务于快速发展和变化的业务,为了能够高效响应业务的数据需求,一方面存在烟囱式建设的情况,指标管理也较为粗放;另一方面对于线上的表和任务往往是只做加法不做减法,带来额外的计算和存储成本。<br> 基于上述现状,衍生出如下问题:</p> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"><strong style="background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;">管理者视角:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 看不清数仓整体建设情况 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 看不清成本增长和分布 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 内外部用数效率和数据质量提升难 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 看不清研发规范落地效果 </section></li> </ul> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"><strong style="background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;">数仓RD视角:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 名下哪些资产有问题,有什么问题 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 模型完备度如何,哪些业务过程建设较薄弱 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 模型复用率如何,哪些模型没人用 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 哪些规范没有执行好 </section></li> </ul> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"><strong style="background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;">外部用户视角:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 找数、用数难,用户效率低 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 准确性、及时性、一致性等问题频出 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 报表、邮件、播报权限难管控 </section></li> </ul> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 为了能够系统性解决上述问题,我们在24年将数据治理规划成年度重点项目。我们通过制定标准、夯实基建、搭建指标库和数仓地图等手段来进行事前预防和事中监控以及辅助提效,<code style="color: rgb(255, 124, 5);line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(240, 170, 12, 0.02);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: Consolas, Monaco, Menlo, monospace;word-break: break-all;">数仓评估体系作为事后的评价和复盘工具,则是贯穿整体治理过程。</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-imgfileid="100018122" data-ratio="0.5361111111111111" src="/upload/3f271de32d463f3ce7c26d7021c1c022.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 以上是数据治理的整体规划及数仓评估体系所处的位置,我们对数仓评估体系的定位是:<code style="color: rgb(255, 124, 5);line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(240, 170, 12, 0.02);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: Consolas, Monaco, Menlo, monospace;word-break: break-all;">基于客观事实进行数仓现状及问题的量化分析及横纵向对比,实现基于结果指标和治理项驱动的数据治理及效果回收。</code></p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 20px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">2.2 需要解决的技术问题</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;">✓数仓评估指标的设计与落地<br>✓“客观事实”数据的获取与处理<br>✓存量的问题怎么治理<br>✓增量的问题怎么管控<br>✓如何不断完善和健壮评估体系</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 22px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">3 设计思路</span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 整个评估体系分为结果评估和过程评估两大模块。我们通过结果评估中关于效率、质量、成本、模型相关的结果指标,观测数仓治理目标达成情况;通过过程评估的治理项驱动数仓RD进行具体问题的治理。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 20px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">3.1 整体架构设计</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 整个数仓评估体系大致上可以分为三层:</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-imgfileid="100018121" data-ratio="0.643661971830986" src="/upload/d7126d8717102513eeb8900703cc3d52.png" data-type="png" data-w="710" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> <strong style="color: rgb(0, 0, 0);background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;">指标层:</strong> 以数据处理层产出的数据模型为基础、结果指标和过程指标体系为目标进行指标加工,产出相应的指标结果表,支持趋势分析和横向的对比分析 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> <strong style="color: rgb(0, 0, 0);background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;">数据处理层:</strong> 对数据源层获取到的数据为基础,进行数据清洗和建模 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> <strong style="color: rgb(0, 0, 0);background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;">数据源层:</strong> 整合数据源,包括Hive元数据、平台查询日志、告警日志、账单数据、治理项规则、组织架构等 </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 20px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">3.2 产品形态设计</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 整个评估体系规划为结果评估、过程评估两大模块,分别对应结果指标和治理项两套指标体系。结果评估用于观测当前现状及趋势,看的是整体表现;过程评估驱动日常的数据治理,直击各RD的问题资产及具体的问题明细。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-imgfileid="100018124" data-ratio="0.14489311163895488" src="/upload/fd732f6c615f6864968368d62a06d55a.jpg" data-type="jpeg" data-w="842" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 18px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">结果评估</span><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 用于呈现当前在效率、质量、成本、模型相关的指标现状,并进行横纵向的量化分析,支持组织、组件、人等粒度的下钻分析。数据主要来自于分析师和产品运营等数据使用方的数据查询日志进行统计分析、对数据质量监控服务日志的统计分析、以及人工打标线上问题或事故的统计分析。</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-imgfileid="100018125" data-ratio="0.32963374028856823" src="/upload/358a97b0eed95982a5b5f1df6c5b611f.jpg" data-type="jpeg" data-w="901" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 18px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">过程评估</span><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 通过对日常问题、规范的抽象总结,形成各类治理项。目前包含效率、质量、研发、成本四大类治理项,汇集成治理工作台。通过治理项驱动数仓RD进行数据治理。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-imgfileid="100018123" data-ratio="0.48956158663883087" src="/upload/8f3e76dfb9730bbad48430bc63e6f104.jpg" data-type="jpeg" data-w="958" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 20px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">3.2 指标体系搭建</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 数仓评估体系的指标体系大致上可以两层。第一层是过程评估关注的每个具体问题对应的治理项;第二层是结果评估关注的结果指标。<br> <code style="color: rgb(255, 124, 5);line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(240, 170, 12, 0.02);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: Consolas, Monaco, Menlo, monospace;word-break: break-all;">治理项</code>,来自于对日常规范的抽象,是每一个具体的问题的检查项,是数据治理的最细粒度。我们一期围绕效率、质量、研发、成本四方面一共设置了24个治理项。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-imgfileid="100018130" data-ratio="0.7657407407407407" src="/upload/f79404061f34efe6cce7eb342a2bb38c.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> <code style="color: rgb(255, 124, 5);line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(240, 170, 12, 0.02);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: Consolas, Monaco, Menlo, monospace;word-break: break-all;">结果指标</code>,是各类问题的聚合结果,是某一类问题或者单个核心问题的当前现状表现。我们对管理者视角、RD视角、用户视角所存在的问题进行了抽象和归类成具体的治理项,设置如下指标体系:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> <strong style="color: rgb(0, 0, 0);background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;">效率上:</strong> 我们会关注效率分,这是一个基于平均运行时长、ODS穿透率、复杂SQL占比加权统计出来的复合指标,用来观测评估业务侧通过即席查询使用数据时的效率情况。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> <strong style="color: rgb(0, 0, 0);background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;">质量上:</strong> 我们关注线上问题次数 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> <strong style="color: rgb(0, 0, 0);background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;">成本上:</strong> 我们关注成本整体的增长率、分组件的成本分布和增长情况,并且关注具体到业务和个人的成本分布。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> <strong style="color: rgb(0, 0, 0);background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;">模型上:</strong> 我们关注整体的完备度、复用率、稳定性、规范性等。 </section></li> </ul> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 22px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">4 结果呈现</span><span style="display: none;"></span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 20px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">4.1 结果评估模块展示</span><span style="display: none;"></span></h3> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 18px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">效率评估</span><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 实现效率分的横向和纵向对比,支持分业务下钻至具体的个人以及具体的某次查询。通过内部模型完备、宣导加提效工具的赋能,辅助业务侧的运营、产品、分析师等同事,提升日常查询数据的效率。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-imgfileid="100018128" data-ratio="0.42685185185185187" src="/upload/69076903932054de5d9e56fcac75004d.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 18px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">质量评估</span><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 实现线上质量问题的趋势分析。这块目前以手动填报为主,后续会引入质量监控、任务告警等数据,作为质量问题的评估依据。当前还是侧重于业务感知问题记录和复盘。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-imgfileid="100018126" data-ratio="0.42314814814814816" src="/upload/adcc5c9632657f3036778d1037bb1679.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 18px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">成本评估</span><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 成本这块,我们重点关注月度增长趋势是否在可控的范围内,后续会通过任务及存储的系统性治理,驱动成本的下降,今年的重心还是在内部模型相关治理上。</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-imgfileid="100018127" data-ratio="0.22314814814814815" src="/upload/ee2689bc1660959c217f2fdf29ef426b.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 成本拆解至组件、组织和个人:</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-imgfileid="100018129" data-ratio="0.5064814814814815" src="/upload/74756394ccdbdbff7e4d748d07a1b742.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 18px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">模型评估</span><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 这块是今年投入时间最多的部分。我们通过完备度、复用率、稳定性、规范性指标,观测治理的成果。通过目标驱动RD使用治理工作台进行各类问题下具体治理项的治理。</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-imgfileid="100018134" data-ratio="0.5064814814814815" src="/upload/4c9d4d07993f413cd637e074583c75ff.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 20px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">4.2 过程评估模块展示</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 本模块呈现各RD当前存在问题的资产明细,通过点击资产名称,可跳转查看具体问题项。也可通过控件筛选查询当前关注的治理项。</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-imgfileid="100018135" data-ratio="0.4787037037037037" src="/upload/78152ff4dec47f7e02363ae533d1a431.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 资产问题治理项明细:</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-imgfileid="100018131" data-ratio="0.17222222222222222" src="/upload/01264bf4593d4acf563efdc6aba0e6e3.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 通过治理报告可观测当前目标的达成情况,及本周或本月的治理进展。并且通过新增资产监控实现增量问题的管控。</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-imgfileid="100018133" data-ratio="0.5287037037037037" src="/upload/46e117e321ce9e26765e417b60c1caf6.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 20px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">4.3 阶段性治理收益</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 过去一年,我们通过数仓评估体系驱动的数据治理,重点还是在于数仓内部的治理。偏向于完备度、复用率、稳定性和规范性。<code style="color: rgb(255, 124, 5);line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(240, 170, 12, 0.02);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: Consolas, Monaco, Menlo, monospace;word-break: break-all;">磨刀不误砍柴工,勤修炼内功,为后续的效率和质量治理奠定基础。</code></p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 18px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">治理收益如下:</span><span style="display: none;"></span></h4> <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-imgfileid="100018132" data-ratio="0.2462962962962963" src="/upload/49021acaad1f33ba5bce81d63d9ecd69.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;border-style: none;border-width: 3px;border-color: rgba(0, 0, 0, 0.4);border-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 驱动完备度从年初的50.2%<code style="color: rgb(255, 124, 5);line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(240, 170, 12, 0.02);width: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: Consolas, Monaco, Menlo, monospace;word-break: break-all;">提升至93.97%,净提升43.77%</code> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 驱动复用率从年初的51.65%<code style="color: rgb(255, 124, 5);line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(240, 170, 12, 0.02);width: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: Consolas, Monaco, Menlo, monospace;word-break: break-all;">提升至88.61%,净提升36.96%</code> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 驱动稳定性从年初的76.27%<code style="color: rgb(255, 124, 5);line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(240, 170, 12, 0.02);width: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: Consolas, Monaco, Menlo, monospace;word-break: break-all;">提升至94.45%,净提升18.18%</code> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 驱动规范性从年初的76.56%<code style="color: rgb(255, 124, 5);line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(240, 170, 12, 0.02);width: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: Consolas, Monaco, Menlo, monospace;word-break: break-all;">提升至94.61%,净提升18.05%</code> </section></li> </ul> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 18px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">给数仓带来的核心变化是:</span><span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"> 完备度治理驱动24年新上线模型达到上一年<code style="color: rgb(255, 124, 5);line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(240, 170, 12, 0.02);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: Consolas, Monaco, Menlo, monospace;word-break: break-all;">2.6倍,增长161%</code>,对应的符合复用标准的模型数不降反升,<code style="color: rgb(255, 124, 5);line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(240, 170, 12, 0.02);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: Consolas, Monaco, Menlo, monospace;word-break: break-all;">说明模型更贴合当前的业务场景及业务过程且复用程度更高</code>,另外治理过程整合下线无用模型,一定程度上减少了存储空间占用。<br> 最终完备度达到95%,则说明内部承接的需求,95%都可以通过模型层满足,过往只能满足50%左右。<br> 在规范性上,之前一直存在的<code style="color: rgb(255, 124, 5);line-height: 1.8em;letter-spacing: 0em;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(240, 170, 12, 0.02);width: auto;height: auto;margin-left: 2px;margin-right: 2px;padding: 2px 4px;border-style: none;border-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 4px;font-family: Consolas, Monaco, Menlo, monospace;word-break: break-all;">跨层穿透问题、回流引用问题、引用外部门表问题、注释缺失问题、缺依赖问题等存量问题基本治理完毕并得到了控制</code>,后续持续观测即可。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;"><span style="display: none;"></span><span style="font-size: 22px;line-height: 1.5em;letter-spacing: 0em;font-weight: bold;display: block;">5 未来规划</span><span style="display: none;"></span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 通过定期复盘,持续迭代和完善治理项,使评估更准确、更全面 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 慢慢由内部的治理,转向外部效率&质量治理提升 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 挖掘成本存在浪费的业务或个人,通过治理驱动降本增效 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);line-height: 1.8em;letter-spacing: 0em;"> 逐步推广至仓外评估和治理 </section></li> </ul> <hr data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-style: solid none none;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-color: rgb(0, 0, 0) rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.4);border-radius: 0px;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: 1px;"> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding: 10px 10px 10px 20px;border-top: 3px none rgba(0, 0, 0, 0.4);border-bottom: 3px none rgba(0, 0, 0, 0.4);border-right: 3px none rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-radius: 0px;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgba(0, 0, 0, 0.05);width: auto;height: auto;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;overflow: auto;"> <span style="display: none;color: rgb(0, 0, 0);font-size: 16px;line-height: 1.5em;letter-spacing: 0em;"></span> <p style="text-indent: 0em;padding-top: 8px;padding-bottom: 8px;color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;">关于作者</p> </blockquote> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;">邱狄凡,转转大数据开发工程师,C2&新媒体数仓负责人,数据治理数仓主R。</p> <p data-tool="mdnice编辑器" style="line-height: 1.8em;letter-spacing: 0em;text-indent: 0em;padding-top: 8px;padding-bottom: 8px;"><span style="letter-spacing: 0em;text-indent: 0em;background-color: rgba(0, 0, 0, 0.05);word-spacing: 0em;"><br></span></p> <p style="text-align: left;margin-bottom: 0px;"><span style="text-align: left;">想了解更多转转公司的业务实践,欢迎点击关注下方公众号:</span></p> <section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-id="MzU0OTExNzYwNg==" data-pluginname="mpprofile" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/T81bAV0NNNic0ML4zU2J1rQjcSGup0pfw0feOGibOibN90LoE5BEauYhW8jzaz3RdP9icWED8JwI6jsU6nTPhaNibnw/0?wx_fmt=png" data-nickname="大转转FE" data-alias="zhuanzhuanfe" data-signature="定期分享一些团队对前端的想法与沉淀" data-from="0" data-is_biz_ban="0"></mp-common-profile> </section> <section class="mp_profile_iframe_wrp"> <mp-common-profile class="js_uneditable custom_select_card mp_profile_iframe" data-id="MzI1OTQ1NjA1OA==" data-pluginname="mpprofile" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/DicJKAuVt0L6kxKJp3xVon3ic7GCs3M62nmZiaFegJ4KXnGDncRZrsMxKuoxNpaAzwDCZyYiaTxzVjJA0Jxu2xl9MA/0?wx_fmt=png" data-nickname="转转QA" data-alias="" data-signature="转转QA伐木累" data-from="0" data-is_biz_ban="0"></mp-common-profile> </section> <p style="margin-bottom: 0px;"><br></p> </section> <p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p>