作者:微信小助手
<section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">曾几何时,对于Java的序列化的认知一直停留在:「实现个</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Serializbale</span></code> <span style="letter-spacing: 1px;font-size: 15px;">接口」不就好了的状态,直到 ...</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="font-size: 15px;letter-spacing: 1px;">所以这次抽时间再次重新捧起了尘封已久的《Java编程思想》,就像之前梳理《枚举部分知识》一样,把「序列化和反序列化」这块的知识点又重新审视了一遍。</span> </section> <h1 style="box-sizing: inherit;font-size: 26px;margin: 22px 8px 20px;font-family: "PingFang SC", "Helvetica Neue", "Microsoft YaHei UI", "Microsoft YaHei", "Noto Sans CJK SC", Sathu, EucrosiaUPC, Arial, Helvetica, sans-serif;font-weight: 600;min-height: 1rem;border-width: initial;border-style: none;border-color: initial;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);line-height: 2em;"><span style="box-sizing: inherit;letter-spacing: 1px;font-size: 20px;color: rgb(49, 133, 155);">序列化是干啥用的?</span></h1> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">序列化的原本意图是希望对一个Java对象作一下“变换”,变成字节序列,这样一来方便持久化存储到磁盘,避免程序运行结束后对象就从内存里消失,另外变换成字节序列也更便于网络运输和传播,所以概念上很好理解:</span> </section> <ul style="box-sizing: inherit;margin-bottom: 20px;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);margin-left: 8px;margin-right: 8px;" class="list-paddingleft-2"> <li style="box-sizing: inherit;line-height: 1.875em;letter-spacing: 1px;font-size: 15px;"> <section style="box-sizing: inherit;text-align: justify;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;"><span style="letter-spacing: 1px;box-sizing: inherit;font-weight: 700;color: rgb(53, 179, 120);">序列化</span>:把Java对象转换为字节序列。</span> </section></li> <li style="box-sizing: inherit;line-height: 1.875em;letter-spacing: 1px;font-size: 15px;"> <section style="box-sizing: inherit;text-align: justify;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;"><span style="letter-spacing: 1px;box-sizing: inherit;font-weight: 700;color: rgb(53, 179, 120);">反序列化</span>:把字节序列恢复为原先的Java对象。</span> </section></li> </ul> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <img data-ratio="0.46096345514950166" src="/upload/943cb68086cbd2958c8d51172f7c4fdf.png" data-type="png" data-w="2408" style="box-sizing: border-box;border-width: 0px;border-style: initial;border-color: initial;margin-right: auto;margin-left: auto;max-width: 80%;vertical-align: middle;cursor: zoom-in;"> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">而且序列化机制从某种意义上来说也弥补了平台化的一些差异,毕竟转换后的字节流可以在其他平台上进行反序列化来恢复对象。</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">事情就是那么个事情,看起来很简单,不过后面的东西还不少,请往下看。</span> </section> <hr style="box-sizing: content-box;height: 0px;overflow: visible;border-right: none;border-bottom: none;border-left: none;border-top-style: solid;border-top-color: rgb(238, 238, 238);background: 0px 0px rgb(255, 255, 255);margin-bottom: 20px;zoom: 1;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;"> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;background-color: rgb(255, 255, 255);font-family: "PingFang SC", "Helvetica Neue", "Microsoft YaHei UI", "Microsoft YaHei", "Noto Sans CJK SC", Sathu, EucrosiaUPC, Arial, Helvetica, sans-serif;font-weight: 600;font-size: 20px;color: rgb(49, 133, 155);">对象如何序列化?</span> <br> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">然而Java目前并没有一个关键字可以直接去定义一个所谓的“可持久化”对象。</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">对象的持久化和反持久化需要靠程序员在代码里手动<span style="letter-spacing: 1px;box-sizing: inherit;font-weight: 700;color: rgb(53, 179, 120);">显式地</span>进行序列化和反序列化还原的动作。</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">举个例子,假如我们要对</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Student</span></code> <span style="letter-spacing: 1px;font-size: 15px;">类对象序列化到一个名为</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">student.txt</span></code> <span style="letter-spacing: 1px;font-size: 15px;">的文本文件中,然后再通过文本文件反序列化成</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Student</span></code> <span style="letter-spacing: 1px;font-size: 15px;">类对象:</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <img data-ratio="0.47619047619047616" src="/upload/819e4f6a7a0b98b4dd82fc01f5a07ef0.png" data-type="png" data-w="1806" style="box-sizing: border-box;border-width: 0px;border-style: initial;border-color: initial;margin-right: auto;margin-left: auto;max-width: 80%;vertical-align: middle;cursor: zoom-in;"> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">1、Student类定义</span> </section> <pre style="box-sizing: border-box;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;word-break: break-word;overflow-wrap: normal;overflow: auto;margin-bottom: 20px;padding: 1em;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;line-height: 1.5;background: rgb(246, 246, 246);text-align: left;"> <section style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;border-width: initial;border-style: none;border-color: initial;border-radius: 0px;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;overflow: visible;word-break: normal;display: block;text-align: justify;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;"><span style="box-sizing: inherit;color: rgb(215, 58, 73);">public</span> <span style="box-sizing: inherit;"><span style="box-sizing: inherit;color: rgb(215, 58, 73);">class</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(111, 66, 193);">Student</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(111, 66, 193);">implements</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(111, 66, 193);">Serializable</span><span style="box-sizing: inherit;"> </span></span>{<br><br> <span style="box-sizing: inherit;color: rgb(215, 58, 73);">private</span> String name;<br> <span style="box-sizing: inherit;color: rgb(215, 58, 73);">private</span> Integer age;<br> <span style="box-sizing: inherit;color: rgb(215, 58, 73);">private</span> Integer score;<br> <br> <span style="box-sizing: inherit;color: rgb(106, 115, 125);">@Override</span><br> <span style="box-sizing: inherit;"><span style="box-sizing: inherit;color: rgb(215, 58, 73);">public</span> String <span style="box-sizing: inherit;color: rgb(97, 174, 238);">toString</span><span style="box-sizing: inherit;">()</span> </span>{<br> <span style="box-sizing: inherit;color: rgb(215, 58, 73);">return</span> <span style="box-sizing: inherit;color: rgb(3, 47, 98);">"Student:"</span> + <span style="box-sizing: inherit;color: rgb(3, 47, 98);">'n'</span> +<br> <span style="box-sizing: inherit;color: rgb(3, 47, 98);">"name = "</span> + <span style="box-sizing: inherit;color: rgb(215, 58, 73);">this</span>.name + <span style="box-sizing: inherit;color: rgb(3, 47, 98);">'n'</span> +<br> <span style="box-sizing: inherit;color: rgb(3, 47, 98);">"age = "</span> + <span style="box-sizing: inherit;color: rgb(215, 58, 73);">this</span>.age + <span style="box-sizing: inherit;color: rgb(3, 47, 98);">'n'</span> +<br> <span style="box-sizing: inherit;color: rgb(3, 47, 98);">"score = "</span> + <span style="box-sizing: inherit;color: rgb(215, 58, 73);">this</span>.score + <span style="box-sizing: inherit;color: rgb(3, 47, 98);">'n'</span><br> ;<br> }<br> <br> <em style="box-sizing: inherit;"><span style="box-sizing: inherit;color: rgb(106, 115, 125);">// ... 其他省略 ...</span></em><br>}<br></span> </section></pre> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">2、序列化</span> </section> <pre style="box-sizing: border-box;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;word-break: break-word;overflow-wrap: normal;overflow: auto;margin-bottom: 20px;padding: 1em;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;line-height: 1.5;background: rgb(246, 246, 246);text-align: left;"> <section style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;border-width: initial;border-style: none;border-color: initial;border-radius: 0px;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;overflow: visible;word-break: normal;display: block;text-align: justify;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;"><span style="box-sizing: inherit;"><span style="box-sizing: inherit;color: rgb(215, 58, 73);">public</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(215, 58, 73);">static</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(215, 58, 73);">void</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(111, 66, 193);">serialize</span><span style="box-sizing: inherit;"><span style="box-sizing: inherit;">(<span style="box-sizing: inherit;"> </span>)</span> </span><span style="color: rgb(198, 120, 221);box-sizing: inherit;">throws</span><span style="box-sizing: inherit;"> IOException</span> </span>{<br><br> Student student = <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> Student();<br> student.setName(<span style="box-sizing: inherit;color: rgb(3, 47, 98);">"CodeSheep"</span>);<br> student.setAge( <span style="box-sizing: inherit;color: rgb(209, 154, 102);">18</span> );<br> student.setScore( <span style="box-sizing: inherit;color: rgb(209, 154, 102);">1000</span> );<br><br> ObjectOutputStream objectOutputStream = <br> <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> ObjectOutputStream( <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> FileOutputStream( <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> File(<span style="box-sizing: inherit;color: rgb(3, 47, 98);">"student.txt"</span>) ) );<br> objectOutputStream.writeObject( student );<br> objectOutputStream.close();<br> <br> System.<span style="box-sizing: inherit;color: rgb(215, 58, 73);">out</span>.println(<span style="box-sizing: inherit;color: rgb(3, 47, 98);">"序列化成功!已经生成student.txt文件"</span>);<br> System.<span style="box-sizing: inherit;color: rgb(215, 58, 73);">out</span>.println(<span style="box-sizing: inherit;color: rgb(3, 47, 98);">"=============================================="</span>);<br>}<br></span> </section></pre> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">3、反序列化</span> </section> <pre style="box-sizing: border-box;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;word-break: break-word;overflow-wrap: normal;overflow: auto;margin-bottom: 20px;padding: 1em;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;line-height: 1.5;background: rgb(246, 246, 246);text-align: left;"> <section style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;border-width: initial;border-style: none;border-color: initial;border-radius: 0px;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;overflow: visible;word-break: normal;display: block;text-align: justify;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;"><span style="box-sizing: inherit;"><span style="box-sizing: inherit;color: rgb(215, 58, 73);">public</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(215, 58, 73);">static</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(215, 58, 73);">void</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(111, 66, 193);">deserialize</span><span style="box-sizing: inherit;"><span style="box-sizing: inherit;">(<span style="box-sizing: inherit;"> </span>)</span> </span><span style="color: rgb(198, 120, 221);box-sizing: inherit;">throws</span><span style="box-sizing: inherit;"> IOException, ClassNotFoundException</span> </span>{<br> ObjectInputStream objectInputStream = <br> <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> ObjectInputStream( <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> FileInputStream( <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> File(<span style="box-sizing: inherit;color: rgb(3, 47, 98);">"student.txt"</span>) ) );<br> Student student = (Student) objectInputStream.readObject();<br> objectInputStream.close();<br> <br> System.<span style="box-sizing: inherit;color: rgb(215, 58, 73);">out</span>.println(<span style="box-sizing: inherit;color: rgb(3, 47, 98);">"反序列化结果为:"</span>);<br> System.<span style="box-sizing: inherit;color: rgb(215, 58, 73);">out</span>.println( student );<br>}<br></span> </section></pre> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">4、运行结果</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">控制台打印:</span> </section> <pre style="box-sizing: border-box;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;word-break: break-word;overflow-wrap: normal;overflow: auto;margin-bottom: 20px;padding: 1em;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;line-height: 1.5;background: rgb(246, 246, 246);text-align: left;"> <section style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;border-width: initial;border-style: none;border-color: initial;border-radius: 0px;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;overflow: visible;word-break: normal;display: block;text-align: justify;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;">序列化成功!已经生成student.txt文件<br>==============================================<br>反序列化结果为:<br><span style="box-sizing: inherit;color: rgb(34, 134, 58);">Student:</span><br>name = CodeSheep<br>age = <span style="box-sizing: inherit;color: rgb(209, 154, 102);">18</span><br>score = <span style="box-sizing: inherit;color: rgb(209, 154, 102);">1000</span><br></span> </section></pre> <hr style="box-sizing: content-box;height: 0px;overflow: visible;border-right: none;border-bottom: none;border-left: none;border-top-style: solid;border-top-color: rgb(238, 238, 238);background: 0px 0px rgb(255, 255, 255);margin-bottom: 20px;zoom: 1;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;"> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="font-size: 20px;letter-spacing: 1px;background-color: rgb(255, 255, 255);font-family: "PingFang SC", "Helvetica Neue", "Microsoft YaHei UI", "Microsoft YaHei", "Noto Sans CJK SC", Sathu, EucrosiaUPC, Arial, Helvetica, sans-serif;font-weight: 600;color: rgb(49, 133, 155);">Serializable接口有何用?</span> <br> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">上面在定义</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Student</span></code> <span style="letter-spacing: 1px;font-size: 15px;">类时,实现了一个</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Serializable</span></code> <span style="letter-spacing: 1px;font-size: 15px;">接口,然而当我们点进</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Serializable</span></code> <span style="letter-spacing: 1px;font-size: 15px;">接口内部查看,发现它<span style="letter-spacing: 1px;box-sizing: inherit;font-weight: 700;color: rgb(53, 179, 120);">竟然是一个空接口</span>,并没有包含任何方法!</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <img data-ratio="0.8259668508287292" src="/upload/d2680f6d13a610e433344216dd52679c.png" data-type="png" data-w="724" style="box-sizing: border-box;border-width: 0px;border-style: initial;border-color: initial;margin-right: auto;margin-left: auto;max-width: 80%;vertical-align: middle;cursor: zoom-in;"> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">试想,如果上面在定义</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Student</span></code> <span style="letter-spacing: 1px;font-size: 15px;">类时忘了加</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">implements Serializable</span></code> <span style="letter-spacing: 1px;font-size: 15px;">时会发生什么呢?</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">实验结果是:此时的程序运行<span style="letter-spacing: 1px;box-sizing: inherit;font-weight: 700;color: rgb(53, 179, 120);">会报错</span>,并抛出</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">NotSerializableException</span></code> <span style="letter-spacing: 1px;font-size: 15px;">异常:</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <img data-ratio="0.24501758499413834" src="/upload/dbe9b1da09e4bafe5e87bc31af917c7f.png" data-type="png" data-w="1706" style="box-sizing: border-box;border-width: 0px;border-style: initial;border-color: initial;margin-right: auto;margin-left: auto;max-width: 80%;vertical-align: middle;cursor: zoom-in;"> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">我们按照错误提示,由源码一直跟到</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">ObjectOutputStream</span></code> <span style="letter-spacing: 1px;font-size: 15px;">的</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">writeObject0()</span></code> <span style="letter-spacing: 1px;font-size: 15px;">方法底层一看,才恍然大悟:</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <img data-ratio="0.7327433628318584" src="/upload/36d2b1c6cc90a4e5408f58052fb6c9e8.png" data-type="png" data-w="1130" style="box-sizing: border-box;border-width: 0px;border-style: initial;border-color: initial;margin-right: auto;margin-left: auto;max-width: 80%;vertical-align: middle;cursor: zoom-in;"> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">如果一个对象既不是<span style="letter-spacing: 1px;box-sizing: inherit;font-weight: 700;color: rgb(53, 179, 120);">字符串</span>、<span style="letter-spacing: 1px;box-sizing: inherit;font-weight: 700;color: rgb(53, 179, 120);">数组</span>、<span style="letter-spacing: 1px;box-sizing: inherit;font-weight: 700;color: rgb(53, 179, 120);">枚举</span>,而且也没有实现</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Serializable</span></code> <span style="letter-spacing: 1px;font-size: 15px;">接口的话,在序列化时就会抛出</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">NotSerializableException</span></code> <span style="letter-spacing: 1px;font-size: 15px;">异常!</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">哦,我明白了!</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">原来</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Serializable</span></code> <span style="letter-spacing: 1px;font-size: 15px;">接口也仅仅只是做一个标记用!!!</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">它告诉代码只要是实现了</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Serializable</span></code> <span style="letter-spacing: 1px;font-size: 15px;">接口的类都是可以被序列化的!然而真正的序列化动作不需要靠它完成。</span> </section> <hr style="box-sizing: content-box;height: 0px;overflow: visible;border-right: none;border-bottom: none;border-left: none;border-top-style: solid;border-top-color: rgb(238, 238, 238);background: 0px 0px rgb(255, 255, 255);margin-bottom: 20px;zoom: 1;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: left;white-space: normal;"> <h1 style="box-sizing: inherit;font-size: 26px;margin: 22px 8px 20px;font-family: "PingFang SC", "Helvetica Neue", "Microsoft YaHei UI", "Microsoft YaHei", "Noto Sans CJK SC", Sathu, EucrosiaUPC, Arial, Helvetica, sans-serif;font-weight: 600;min-height: 1rem;border-width: initial;border-style: none;border-color: initial;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);line-height: 2em;"><span style="box-sizing: inherit;letter-spacing: 1px;font-size: 20px;color: rgb(49, 133, 155);"><code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);">serialVersionUID</code>号有何用?</span></h1> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">相信你一定经常看到有些类中定义了如下代码行,即定义了一个名为</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">serialVersionUID</span></code> <span style="letter-spacing: 1px;font-size: 15px;">的字段:</span> </section> <pre style="box-sizing: border-box;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;word-break: break-word;overflow-wrap: normal;overflow: auto;margin-bottom: 20px;padding: 1em;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;line-height: 1.5;background: rgb(246, 246, 246);text-align: left;"> <section style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;border-width: initial;border-style: none;border-color: initial;border-radius: 0px;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;overflow: visible;word-break: normal;display: block;text-align: justify;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;"><span style="box-sizing: inherit;color: rgb(215, 58, 73);">private</span> <span style="box-sizing: inherit;color: rgb(215, 58, 73);">static</span> <span style="box-sizing: inherit;color: rgb(215, 58, 73);">final</span> <span style="box-sizing: inherit;color: rgb(215, 58, 73);">long</span> serialVersionUID = -<span style="box-sizing: inherit;color: rgb(209, 154, 102);">4392658638228508589L</span>;<br></span> </section></pre> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="box-sizing: inherit;font-weight: 700;color: rgb(53, 179, 120);letter-spacing: 1px;font-size: 15px;">你知道这句声明的含义吗?为什么要搞一个名为<code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);">serialVersionUID</code>的序列号?</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">继续来做一个简单实验,还拿上面的</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Student</span></code> <span style="letter-spacing: 1px;font-size: 15px;">类为例,我们并没有人为在里面显式地声明一个</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">serialVersionUID</span></code> <span style="letter-spacing: 1px;font-size: 15px;">字段。</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">我们首先还是调用上面的</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">serialize()</span></code> <span style="letter-spacing: 1px;font-size: 15px;">方法,将一个</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Student</span></code> <span style="letter-spacing: 1px;font-size: 15px;">对象序列化到本地磁盘上的</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">student.txt</span></code> <span style="letter-spacing: 1px;font-size: 15px;">文件:</span> </section> <pre style="box-sizing: border-box;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;word-break: break-word;overflow-wrap: normal;overflow: auto;margin-bottom: 20px;padding: 1em;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;line-height: 1.5;background: rgb(246, 246, 246);text-align: left;"> <section style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;border-width: initial;border-style: none;border-color: initial;border-radius: 0px;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;overflow: visible;word-break: normal;display: block;text-align: justify;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;"><span style="box-sizing: inherit;"><span style="box-sizing: inherit;color: rgb(215, 58, 73);">public</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(215, 58, 73);">static</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(215, 58, 73);">void</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(111, 66, 193);">serialize</span><span style="box-sizing: inherit;"><span style="box-sizing: inherit;">()</span> </span><span style="box-sizing: inherit;color: rgb(215, 58, 73);">throws</span><span style="box-sizing: inherit;"> IOException </span></span>{<br><br> Student student = <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> Student();<br> student.setName(<span style="box-sizing: inherit;color: rgb(3, 47, 98);">"CodeSheep"</span>);<br> student.setAge( <span style="box-sizing: inherit;color: rgb(209, 154, 102);">18</span> );<br> student.setScore( <span style="box-sizing: inherit;color: rgb(209, 154, 102);">100</span> );<br><br> ObjectOutputStream objectOutputStream = <br> <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> ObjectOutputStream( <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> FileOutputStream( <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> File(<span style="box-sizing: inherit;color: rgb(3, 47, 98);">"student.txt"</span>) ) );<br> objectOutputStream.writeObject( student );<br> objectOutputStream.close();<br>}<br></span> </section></pre> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">接下来我们在</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Student</span></code> <span style="letter-spacing: 1px;font-size: 15px;">类里面动点手脚,比如在里面再增加一个名为</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">studentID</span></code> <span style="letter-spacing: 1px;font-size: 15px;">的字段,表示学生学号:</span> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: center;white-space: normal;background-color: rgb(255, 255, 255);margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <img data-ratio="0.40471512770137524" src="/upload/c9cd7c9d3b57493f78d3c9697e103fbe.png" data-type="png" data-w="1018" style="box-sizing: border-box;border-width: 0px;border-style: initial;border-color: initial;margin-right: auto;margin-left: auto;max-width: 80%;vertical-align: middle;"> </section> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;font-size: 15px;">这时候,我们拿刚才已经序列化到本地的</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">student.txt</span></code> <span style="letter-spacing: 1px;font-size: 15px;">文件,还用如下代码进行反序列化,试图还原出刚才那个</span> <code style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;margin-right: 3px;margin-left: 3px;padding: 3px 4px;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;background: rgb(246, 246, 246);color: rgb(51, 51, 51);"><span style="letter-spacing: 1px;font-size: 15px;">Student</span></code> <span style="letter-spacing: 1px;font-size: 15px;">对象:</span> </section> <pre style="box-sizing: border-box;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;font-size: 13px;word-break: break-word;overflow-wrap: normal;overflow: auto;margin-bottom: 20px;padding: 1em;border-width: initial;border-style: none;border-color: initial;border-radius: 4px;line-height: 1.5;background: rgb(246, 246, 246);text-align: left;"> <section style="box-sizing: inherit;font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;border-width: initial;border-style: none;border-color: initial;border-radius: 0px;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;overflow: visible;word-break: normal;display: block;text-align: justify;margin-left: 8px;margin-right: 8px;margin-bottom: 20px;line-height: 2em;"> <span style="letter-spacing: 1px;"><span style="box-sizing: inherit;"><span style="box-sizing: inherit;color: rgb(215, 58, 73);">public</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(215, 58, 73);">static</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(215, 58, 73);">void</span><span style="box-sizing: inherit;"> </span><span style="box-sizing: inherit;color: rgb(111, 66, 193);">deserialize</span><span style="box-sizing: inherit;"><span style="box-sizing: inherit;">(<span style="box-sizing: inherit;"> </span>)</span> </span><span style="color: rgb(198, 120, 221);box-sizing: inherit;">throws</span><span style="box-sizing: inherit;"> IOException, ClassNotFoundException</span> </span>{<br> ObjectInputStream objectInputStream = <br> <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> ObjectInputStream( <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> FileInputStream( <span style="box-sizing: inherit;color: rgb(215, 58, 73);">new</span> File(<span style="box-sizing: inherit;color: rgb(3, 47, 98);">"student.txt"</span>) ) );<br> Student student = (Student) objectInputStream.readObject();<br> objectInputStream.close();<br> <br> System.<span style="box-sizing: inherit;color: rgb(215, 58, 73);">out</span>.println(<span style="box-sizing: inherit;color: rgb(3, 47, 98);">"反序列化结果为:"</span>);<br> System.<span style="box-sizing: inherit;color: rgb(215, 58, 73);">out</span>.println( student );<br>}<br></span> </section></pre> <section style="box-sizing: inherit;font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);color: black;margin-left: 8px;margin-right: 8px;margin-b
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding-right: 10px;padding-left: 10px;outline: 0px;max-width: 100%;overflow-wrap: break-word;letter-spacing: 0.034em;white-space: normal;background-color: rgb(255, 255, 255);text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;line-height: 1.6;color: rgb(63, 63, 63);font-size: 16px;box-sizing: border-box !important;"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding-right: 10px;padding-left: 10px;outline: 0px;max-width: 100%;overflow-wrap: break-word;line-height: 1.6;letter-spacing: 0.034em;box-sizing: border-box !important;"> <p data-tool="mdnice编辑器" style="padding-top: 1em;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(74, 74, 74);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;">MyBatis-plus 是一款 Mybatis 增强工具,用于简化开发,提高效率。下文使用缩写 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;max-width: 100%;overflow-wrap: break-word;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);box-sizing: border-box !important;">mp</code> 来简化表示 <code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;max-width: 100%;overflow-wrap: break-word;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);box-sizing: border-box !important;">MyBatis-plus</code>,本文主要介绍 mp 搭配 Spring Boot 的使用。</p> <p data-tool="mdnice编辑器" style="padding-top: 1em;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(74, 74, 74);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;">注:本文使用的 mp 版本是当前最新的3.4.2,早期版本的差异请自行查阅文档</p> <p data-tool="mdnice编辑器" style="padding-top: 1em;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(74, 74, 74);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;">官方网站:baomidou.com/</p> <h2 data-tool="mdnice编辑器" style="margin-top: 1em;margin-bottom: 10px;outline: 0px;font-weight: bold;font-size: 22px;max-width: 100%;color: black;text-align: center;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/lgiaG5BicLkVcNpKaxOrK4vpqklyD75cOpqu6FWd3iaKjomVwzEXPZ7h6v9bhVuHbgu3dZ4hMZ4sycoF6l9SibqKyA/640?wx_fmt=png");background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-top: 38px;margin-bottom: 10px;outline: 0px;max-width: 100%;display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;font-size: 18px;box-sizing: border-box !important;overflow-wrap: break-word !important;">快速入门</span></h2> <ol data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;max-width: 100%;color: black;overflow-wrap: break-word !important;"> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="padding-top: 1em;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(74, 74, 74);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;">创建一个Spring Boot项目</p> </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="padding-top: 1em;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(74, 74, 74);line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;">导入依赖</p> </section></li> </ol> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/6XFhg7ldObw9x643KnRH7R0jiahzQOEe7IibKQqz1s9AGTDQoFXOlsED05LjoQOmibYZ6DDF8qHOIWze2mHwxBpvzoEyicOFz7D4/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 637px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><!-- pom.xml --></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(97, 174, 238);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><?xml version="1.0" encoding="UTF-8"?></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">project</span> <span style="outline: 0px;max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">xmlns</span>=<span style="outline: 0px;max-width: 100%;color: rgb(152, 195, 121);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">"http://maven.apache.org/POM/4.0.0"</span> <span style="outline: 0px;max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">xmlns:xsi</span>=<span style="outline: 0px;max-width: 100%;color: rgb(152, 195, 121);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">"http://www.w3.org/2001/XMLSchema-instance"</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">xsi:schemaLocation</span>=<span style="outline: 0px;max-width: 100%;color: rgb(152, 195, 121);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">modelVersion</span>></span>4.0.0<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">modelVersion</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">parent</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span>org.springframework.boot<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span>spring-boot-starter-parent<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">version</span>></span>2.3.4.RELEASE<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">version</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">relativePath</span>/></span> <span style="outline: 0px;max-width: 100%;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><!-- lookup parent from repository --></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">parent</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span>com.example<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span>mybatis-plus<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">version</span>></span>0.0.1-SNAPSHOT<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">version</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">name</span>></span>mybatis-plus<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">name</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">properties</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">java.version</span>></span>1.8<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">java.version</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">properties</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependencies</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span>org.springframework.boot<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span>spring-boot-starter<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span>org.springframework.boot<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span>spring-boot-starter-test<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">scope</span>></span>test<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">scope</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span>org.springframework.boot<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span>spring-boot-configuration-processor<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span>com.baomidou<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span>mybatis-plus-boot-starter<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">version</span>></span>3.4.2<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">version</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span>mysql<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span>mysql-connector-java<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">scope</span>></span>runtime<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">scope</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span>org.projectlombok<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span>lombok<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependencies</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">build</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">plugins</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">plugin</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span>org.springframework.boot<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span>spring-boot-maven-plugin<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">plugin</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">plugins</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">build</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">project</span>></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <ol start="3" data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;max-width: 100%;color: black;overflow-wrap: break-word !important;"> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 配置数据库 </section></li> </ol> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/6XFhg7ldObw9x643KnRH7R0jiahzQOEe7IibKQqz1s9AGTDQoFXOlsED05LjoQOmibYZ6DDF8qHOIWze2mHwxBpvzoEyicOFz7D4/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 637px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">spring:</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">datasource:</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">driver-class-name:</span> <span style="outline: 0px;max-width: 100%;color: rgb(152, 195, 121);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">com.mysql.cj.jdbc.Driver</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">url:</span> <span style="outline: 0px;max-width: 100%;color: rgb(152, 195, 121);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">jdbc:mysql://localhost:3306/yogurt?serverTimezone=Asia/Shanghai</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">username:</span> <span style="outline: 0px;max-width: 100%;color: rgb(152, 195, 121);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">root</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">password:</span> <span style="outline: 0px;max-width: 100%;color: rgb(152, 195, 121);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">root</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">mybatis-plus:</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">configuration:</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">log-impl:</span> <span style="outline: 0px;max-width: 100%;color: rgb(152, 195, 121);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">org.apache.ibatis.logging.stdout.StdOutImpl</span> <span style="outline: 0px;max-width: 100%;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">#开启SQL语句打印</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <ol start="4" data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;max-width: 100%;color: black;overflow-wrap: break-word !important;"> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 创建一个实体类 </section></li> </ol> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/6XFhg7ldObw9x643KnRH7R0jiahzQOEe7IibKQqz1s9AGTDQoFXOlsED05LjoQOmibYZ6DDF8qHOIWze2mHwxBpvzoEyicOFz7D4/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 637px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">package</span> com.example.mp.po;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span> lombok.Data;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span> java.time.LocalDateTime;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(97, 174, 238);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">@Data</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">public</span> <span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">class</span> <span style="outline: 0px;max-width: 100%;color: rgb(230, 192, 123);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">User</span> </span>{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">private</span> Long id;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">private</span> String name;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">private</span> Integer age;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">private</span> String email;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span
作者:微信小助手
<section> <span style="background-color: rgb(255, 255, 255);color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.544px;text-align: left;">这一讲,我们结合业务场景来讲讲事务消息以及消息的幂等性。</span> <br> </section> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 1.3em;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);border-bottom: 2px solid rgb(239, 112, 96);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 3px;padding: 3px 10px 1px;outline: 0px;max-width: 100%;display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);border-top-right-radius: 3px;border-top-left-radius: 3px;box-sizing: border-box !important;overflow-wrap: break-word !important;">1、业务场景</span><span style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><span style="outline: 0px;max-width: 100%;display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">在电商<span style="color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);">场景</span>中,一般付款成功后,会给用户发放优惠券,一来给用户优惠,二来激励用户继续消费。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="1.9644444444444444" src="/upload/eb7978c9de862438b21802fe9677ce68.png" data-type="png" data-w="225" style="margin-right: auto;margin-left: auto;outline: 0px;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 225px !important;visibility: visible !important;"></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">上面的场景:在电商系统中,会出现付款成功后、准备发优惠券的时候,服务器宕机了。这个时候会造成用户成功付款,却没收到优惠券的情况。这种情况下,我们很容易想到用事务来保证付款和发优惠券的原子性即可:要么付款和发优惠券同时成功,要么同时失败,是不允许其他一个成功,另一个失败的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">但上面,存在一种情况:付款和发优惠券高度耦合,这样子容易出现:发优惠券一直失败,会导致付款一直失败的场景。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">对于这种场景的解决方案:引入消息中间件MQ来解耦。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.6578947368421053" src="/upload/a8fc15aaa7969a7d55bb4ac81eb9e6c8.png" data-type="png" data-w="798"></p> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 1、支付订单 </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 2、发送支付消息 </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 3、消费支付消息 </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 4、发放优惠券 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">上面这个是发放优惠券的流程图。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">但是上述流程中,存在MQ不可用、消息重复的异常情况,进而导致:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;width: 577.422px;white-space: normal;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="color: rgb(0, 0, 0);">产生付款成功,发优惠券失败</span> </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);">优惠券</span>重复发放</span> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">怎样才能确保付款成功后进行优惠券发放并且不会重复呢?这需要引入事务消息和幂等性处理。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 1.3em;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);border-bottom: 2px solid rgb(239, 112, 96);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 3px;padding: 3px 10px 1px;outline: 0px;max-width: 100%;display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);border-top-right-radius: 3px;border-top-left-radius: 3px;box-sizing: border-box !important;overflow-wrap: break-word !important;">2、事务消息</span><span style="outline: 0px;max-width: 100%;display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">首先我们来了解下事务消息。分布式事务是一种抽象的概念。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">那具体的实现呢?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">是有很多种实现的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">在这里,主要介绍:RocketMQ的事务消息。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 20px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">事务消息的流程图</h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);display: flex;flex-direction: column;justify-content: center;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.4202586206896552" src="/upload/c007c3694c63e488121867e21ac8b672.png" data-type="png" data-w="2320" style="margin-right: auto;margin-left: auto;outline: 0px;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 677px !important;visibility: visible !important;"> </figure> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">流程步骤:</h5> <ul data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 1、生产者发送half消息 </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 2、MQ回复ACK确认消息 </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 3、执行本地事务:订单付款。如果订单付款成功,那么就给MQ发送commit消息。如果订单付款失败,就发送rollback消息 </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 4、如果步骤3发送消息失败,这个时候MQ的定时器会检查half消息。MQ回调方法,去检查本地事务的执行情况。如果执行成功,就返回commit消息。如果执行失败,就返回rollback消息。 </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 5、如果MQ收到的是commit消息,此时会把half消息复制到真正的topic中 </section></li> <li style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;max-width: 100%;line-height: 26px;color: rgb(1, 1, 1);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 6、消费者对消息进行消费,下发优惠券 </section></li> </ul> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 1.3em;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);border-bottom: 2px solid rgb(239, 112, 96);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-right: 3px;padding: 3px 10px 1px;outline: 0px;max-width: 100%;display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);border-top-right-radius: 3px;border-top-left-radius: 3px;box-sizing: border-box !important;overflow-wrap: break-word !important;">3、如何使用事务消息</span><span style="outline: 0px;max-width: 100%;display: inline-block;vertical-align: bottom;border-bottom: 36px solid rgb(239, 235, 233);border-right: 20px solid transparent;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">上面,大概知道了事务消息的流程。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">接下来,要知道如何使用。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">还是以付款下发优惠券为例。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 20px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">3.1 发送half消息-MQ回复ACK确认消息</h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/Sqqm3oJYw2jnZD9vXK9lCAMia8Z7b6ukxfTn5yC68ejhFCpxSnI9NofACibd2IASFWnowQMm26XBnbm358FYgJvVx61VNdF2r7/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 657px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> @Override<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> public void finishedOrder(String orderNo, String phoneNumber) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> try {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> // 退房事务消息,topic:完成订单<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> Message msg = new Message(orderFinishedTopic, JSON.toJSONString(orderInfo).getBytes(StandardCharsets.UTF_8));<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> // 发送half消息<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> TransactionSendResult transactionSendResult = orderFinishedTransactionMqProducer.sendMessageInTransaction(msg, null);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> } catch (MQClientException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 20px;max-width: 100%;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">3.2 执行本地事务:付款</h3> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;color: rgb(0, 0, 0);font-size: 16px;text-align: left;background-color: rgb(255, 255, 255);border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/Sqqm3oJYw2jnZD9vXK9lCAMia8Z7b6ukxfTn5yC68ejhFCpxSnI9NofACibd2IASFWnowQMm26XBnbm358FYgJvVx61VNdF2r7/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 657px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;">@Override<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> try {<br style="outline: 0px;max-w
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 12px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;font-size: 13px;">最近在倒腾 Eureka 源码,大环境太卷了,必须得卷点源码才行,另外呢,能够读懂开源项目的源码、解决项目中遇到的问题是实力的象征,是吧?如果只是会用些中间件,那是不够的,和 CRUD 区别不大。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;font-size: 13px;">话不多说,源码走起。本篇是 Eureka 源码分析的开篇,后续会持续分享源码解析的文章。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;font-size: 13px;">首先呢,Eureka 服务的启动入口在这里:EurekaBootStrap.java 的 contextInitialized 方法。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;font-size: 13px;">启动的整个流程图在文末,不想看源码剖析的,可以直接看文末流程图。</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(255, 177, 27);background: rgb(255, 245, 227);"> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 13px;color: black;line-height: 26px;">关于源码的获取直接到官网下载就好了。https://github.com/Netflix/eureka</p> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 13px;color: black;line-height: 26px;">本文已收录到我的 github:https://github.com/Jackson0714/PassJava-Learning</p> </blockquote> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="1.4907407407407407" src="/upload/e14a6d03dd65504477d4ad92dbb15df7.png" data-type="png" data-w="648" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">一、初始化环境</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;font-size: 13px;">打开源码,找到这个<span style="letter-spacing: 0.8px;word-spacing: 0.8px;">启动类,EurekaBootStrap.java,在这个路径下:</span></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 15px 16px 16px;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;background: rgb(40, 44, 52);border-radius: 5px;">\eureka\eureka-core\src\main\java\com\netflix\eureka\EurekaBootStrap.java<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;font-size: 13px;">启动时序图给大家画好了:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-ratio="0.48465703971119134" src="/upload/6c858ee3f1f65749ee9478f8f61680aa.png" data-type="png" data-w="1108" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);"> 初始化环境时序图 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;font-size: 13px;"><span style="display: none;line-height: 0px;"></span>启动代码:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 15px 16px 16px;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;background: rgb(40, 44, 52);border-radius: 5px;"><span style="color: #61aeee;line-height: 26px;">@Override</span><br><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;">public</span> <span style="color: #c678dd;line-height: 26px;">void</span> <span style="color: #61aeee;line-height: 26px;">contextInitialized</span><span style="line-height: 26px;">(ServletContextEvent event)</span> </span>{<br> initEurekaEnvironment();<br> initEurekaServerContext();<br> <span style="color: #5c6370;font-style: italic;line-height: 26px;">// 省略非核心代码</span><br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;font-size: 13px;">分为两步,初始化环境和初始化上下文,先来看第一步。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;font-size: 13px;">初始化环境的方法是 initEurekaEnvironment(),点进去看下这个方法做了什么。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 15px 16px 16px;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;background: rgb(40, 44, 52);border-radius: 5px;">String dataCenter = ConfigurationManager.</code><code style="overflow-x: auto;padding: 15px 16px 16px;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;background: rgb(40, 44, 52);border-radius: 5px;"><span style="letter-spacing: 0.8px;word-spacing: 0.8px;"> getConfigInstance().getString(EUREKA_DATACENTER);</span></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;font-size: 13px;">就是获取配置管理类的一个单例。单例的实现方法用的是 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">双重检测</code> +<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">volatile</code></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 15px 16px 16px;color: rgb(171, 178, 191);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;background: rgb(40, 44, 52);border-radius: 5px;"><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;">public</span> <span style="color: #c678dd;line-height: 26px;">static</span> AbstractConfiguration <span style="color: #61aeee;line-height: 26px;">getConfigInstance</span><span style="line-height: 26px;">()</span> </span>{<br> <span style="color: #c678dd;line-height: 26px;">if</span> (instance == <span style="color: #c678dd;line-height: 26px;">null</span>) {<br> <span style="color: #c678dd;line-height: 26px;">synchronized</span> (ConfigurationManager<span style="line-height: 26px;">.<span style="color: #c678dd;line-height: 26px;">class</span>) </span>{<br> <span style="color: #c678dd;line-height: 26px;">if</span> (instance == <span style="color: #c678dd;line-height: 26px;">null</span>) {<br> instance = getConfigInstance(<span style="color: #c678dd;line-height: 26px;">false</span>));<br> &nbs
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;padding-right: 10px;padding-left: 10px;word-break: break-word;overflow-wrap: break-word;text-align: left;line-height: 1.25;color: rgb(43, 43, 43);font-family: Optima-Regular, Optima, PingFangTC-Light, PingFangSC-light, PingFangTC-light;letter-spacing: 2px;background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.04) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(50, 0, 0, 0.04) 3%, rgba(0, 0, 0, 0) 3%);background-size: 20px 20px;background-position: center center;"> <blockquote data-tool="mdnice编辑器" style="font-size: 0.9em;overflow: auto;padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;text-size-adjust: 100%;line-height: 1.55em;border-radius: 6px;color: rgb(89, 89, 89);box-sizing: inherit;border-width: 1px;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-color: rgba(64, 184, 250, 0.4);background: rgba(64, 184, 250, 0.1);"> <span style="color: RGBA(64, 184, 250, .5);font-size: 34px;line-height: 1;font-weight: 700;">❝</span> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 14px;word-spacing: 2px;line-height: 26px;">悟空 爱学习的程序猿,自主开发了Java学习平台、PMP刷题小程序。目前主修Java、多线程、SpringBoot、SpringCloud、k8s。本公众号不限于分享技术,也会分享工具的使用、人生感悟、读书总结。</p> <span style="float: right;color: RGBA(64, 184, 250, .5);">❞</span> </blockquote> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 25px;"><span style="color: rgb(64, 184, 250);display: none;"></span><span style="display: inline-block;color: rgb(64, 184, 250);">絮叨</span><span style="display: inline-block;color: rgb(64, 184, 250);"></span></h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">这一篇也算是Java并发编程的开篇,看了很多资料,但是轮到自己去整理去总结的时候,发现还是要多看几遍资料才能完全理解。还有一个很重要的点就是,画图是加深印象和检验自己是否理解的一个非常好的方法。</p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 25px;"><span style="color: rgb(64, 184, 250);display: none;"></span><span style="display: inline-block;color: rgb(64, 184, 250);">一、Volatile怎么念?</span><span style="display: inline-block;color: rgb(64, 184, 250);"></span></h1> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img data-ratio="0.6896551724137931" src="/upload/12f6809ae585435fe413dec19ad5fbde.png" data-type="png" data-w="377" style="border-radius: 6px;display: block;margin: 20px auto;object-fit: contain;box-shadow: rgb(153, 153, 153) 2px 4px 7px;"> <figcaption style="margin-top: 5px;text-align: center;font-size: 13px;"> <span style="background-image: url("https://mmbiz.qpic.cn/mmbiz_png/SfAHMuUxqJ3GDO9QVW8Jw3UQCBdeZh0DzescG8KpPVko4awED9GnfZddWPUjZKueyU383FR6ZkJyX5KoeibN5og/640?wx_fmt=png");display: inline-block;width: 18px;height: 18px;background-size: 18px;background-repeat: no-repeat;background-position: center center;margin-right: 5px;margin-bottom: -5px;"></span>volatile怎么念 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">看到这个单词一直不知道怎么发音</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_png/SfAHMuUxqJ3GDO9QVW8Jw3UQCBdeZh0DyaTkdXdfOpJL2fmACzKW4APsQjTboln7BCHsw0h69ayhgJ88vP4RSg/640?wx_fmt=png") 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;letter-spacing: 0px;padding-top: 15px;background: #fff;border-radius: 5px;">英 [ˈvɒlətaɪl] 美 [ˈvɑːlətl]<br><br>adj. [化学] 挥发性的;不稳定的;爆炸性的;反复无常的<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">那Java中volatile又是干啥的呢?</p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 25px;"><span style="color: rgb(64, 184, 250);display: none;"></span><span style="display: inline-block;color: rgb(64, 184, 250);">二、Java中volatile用来干啥?</span><span style="display: inline-block;color: rgb(64, 184, 250);"></span></h1> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;font-size: 15px;color: #595959;list-style-type: circle;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;font-size: 14px;"> Volatile是Java虚拟机提供的 <code style="overflow-wrap: break-word;margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 148, 247);background: rgba(59, 170, 250, 0.1);padding-right: 2px;padding-left: 2px;border-radius: 2px;height: 21px;line-height: 22px;">轻量级</code>的同步机制(三大特性) </section></li> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;font-size: 15px;list-style-type: square;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;font-size: 14px;"> 保证可见性 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;font-size: 14px;"> 不保证原子性 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;font-size: 14px;"> 禁止指令重排 </section></li> </ul> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;">要理解三大特性,就必须知道Java内存模型(JMM),那JMM又是什么呢?</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-ratio="1" src="/upload/bb36e0e2ee8fac7ac0eabd5a750c921c.png" data-type="png" data-w="300" style="border-radius: 6px;display: block;margin: 20px auto;object-fit: contain;box-shadow: rgb(153, 153, 153) 2px 4px 7px;"> <figcaption style="margin-top: 5px;text-align: center;font-size: 13px;"> <span style="background-image: url("https://mmbiz.qpic.cn/mmbiz_png/SfAHMuUxqJ3GDO9QVW8Jw3UQCBdeZh0DzescG8KpPVko4awED9GnfZddWPUjZKueyU383FR6ZkJyX5KoeibN5og/640?wx_fmt=png");display: inline-block;width: 18px;height: 18px;background-size: 18px;background-repeat: no-repeat;background-position: center center;margin-right: 5px;margin-bottom: -5px;"></span>JMM是啥 </figcaption> </figure> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 25px;"><span style="color: rgb(64, 184, 250);display: none;"></span><span style="display: inline-block;color: rgb(64, 184, 250);">三、JMM又是啥?</span><span style="display: inline-block;color: rgb(64, 184, 250);"></span></h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;margin-top: 10px;margin-bottom: 10px;font-size: 14px;word-spacing: 2px;"
作者:微信小助手
<section style="font-size: 16px;"> <pre style="margin-right: 0em;margin-left: 0em;outline: 0px;max-width: 100%;letter-spacing: 0.544px;color: rgb(62, 62, 62);font-size: 14px;widows: 1;word-spacing: 1px;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;caret-color: rgb(74, 74, 74);color: rgb(74, 74, 74);font-family: 微软雅黑, 'Microsoft YaHei';text-align: left;white-space: normal;text-size-adjust: auto;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">Git是现在市面上最流行的版本控制工具,书写良好的commit message能大大提高代码维护的效率。但是在日常开发中由于缺少对于commit message的约束,导致填写内容随意、质量参差不齐,可读性低亦难以维护。在项目中引入commit message规范已是迫在眉睫。<span style="outline: 0px;max-width: 100%;text-align: center;color: rgb(62, 62, 62);letter-spacing: 0.544px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></p><h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;font-size: 22px;max-width: 100%;font-family: 微软雅黑, 'Microsoft YaHei';text-align: left;white-space: normal;text-size-adjust: auto;color: black;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;font-size: 20px;box-sizing: border-box !important;overflow-wrap: break-word !important;">用什么规范?</span></strong></span><span style="outline: 0px;max-width: 100%;font-size: 20px;color: rgb(122, 79, 214);box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></h2><p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;min-height: 1em;caret-color: rgb(74, 74, 74);color: rgb(74, 74, 74);font-family: 微软雅黑, 'Microsoft YaHei';text-align: left;white-space: normal;text-size-adjust: auto;line-heigh
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;padding: 0.6px;font-family: PingFangSC-Light;" data-mpa-powered-by="yiban.io"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">大家好,我是小富~<br></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">对于<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">Nacos</code>大家应该都不太陌生,出身阿里名声在外,能做动态服务发现、配置管理,非常好用的一个工具。然而这样的技术用的人越多面试被问的概率也就越大,如果只停留在使用层面,那面试可能要吃大亏。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">比如我们今天要讨论的话题,<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">Nacos</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 data-ratio="0.6153846153846154" src="/upload/ae93ae681e88bb4d56938308b92a7f0e.png" data-type="png" data-w="832" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">这里我先抛出答案:客户端主动拉的!</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">接下来咱们扒一扒<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">Nacos</code>的源码,来看看它具体是如何实现的?</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>配置中心<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">聊<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">Nacos</code>之前简单回顾下配置中心的由来。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">简单理解配置中心的作用就是对配置统一管理,修改配置后应用可以动态感知,而无需重启。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">因为在传统项目中,大多都采用静态配置的方式,也就是把配置信息都写在应用内的<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">yml</code>或<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">properties</code>这类文件中,如果要想修改某个配置,通常要重启应用才可以生效。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">但有些场景下,比如我们想要在应用运行时,通过修改某个配置项,实时的控制某一个功能的开闭,频繁的重启应用肯定是不能接受的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">尤其是在微服务架构下,我们的应用服务拆分的粒度很细,少则几十多则上百个服务,每个服务都会有一些自己特有或通用的配置。假如此时要改变通用配置,难道要我挨个改几百个服务配置?很显然这不可能。所以为了解决此类问题配置中心应运而生。</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-ratio="0.4604105571847507" src="/upload/668df0077c5f6179e4f56ba9a10091a3.png" data-type="png" data-w="1364" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 配置中心 </figcaption> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>推与拉模型<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">客户端与配置中心的数据交互方式其实无非就两种,要么推<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">push</code>,要么拉<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">pull</code>。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;"><strong style="font-weight: border;color: #0e88eb;">推模型</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">客户端与服务端建立<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">TCP</code>长连接,当服务端配置数据有变动,立刻通过建立的长连接将数据推送给客户端。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">优势:长链接的优点是实时性,一旦数据变动,立即推送变更数据给客户端,而且对于客户端而言,这种方式更为简单,只建立连接接收数据,并不需要关心是否有数据变更这类逻辑的处理。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">弊端:长连接可能会因为网络问题,导致不可用,也就是俗称的<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">假死</code>。连接状态正常,但实际上已无法通信,所以要有的心跳机制<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">KeepAlive</code>来保证连接的可用性,才可以保证配置数据的成功推送。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;"><strong style="font-weight: border;color: #0e88eb;">拉模型</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">客户端主动的向服务端发请求拉配置数据,常见的方式就是轮询,比如每3s向服务端请求一次配置数据。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">轮询的优点是实现比较简单。但弊端也显而易见,轮询无法保证数据的实时性,什么时候请求?间隔多长时间请求一次?都是不得不考虑的问题,而且轮询方式对服务端还会产生不小的压力。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>长轮询<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">开篇我们就给出了答案,<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">nacos</code>采用的是客户端主动拉<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">pull</code>模型,应用长轮询(<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">Long Polling</code>)的方式来获取配置数据。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">额?以前只听过轮询,长轮询又是什么鬼?它和传统意义上的轮询(暂且叫短轮询吧,方便比较)有什么不同呢?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;"><strong style="font-weight: border;color: #0e88eb;">短轮询</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">不管服务端配置数据是否有变化,不停的发起请求获取配置,比如支付场景中前段JS轮询订单支付状态。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">这样的坏处显而易见,由于配置数据并不会频繁变更,若是一直发请求,势必会对服务端造成很大压力。还会造成推送数据的延迟,比如:每10s请求一次配置,如果在第11s时配置更新了,那么推送将会延迟9s,等待下一次请求。</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-ratio="0.3181818181818182" src="/upload/f0cb7564fbbd9a1ba74ba8d33a00e522.png" data-type="png" data-w="528" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">为了解决短轮询的问题,有了长轮询方案。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;"><strong style="font-weight: border;color: #0e88eb;">长轮询</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">长轮询可不是什么新技术,它不过是由服务端控制响应客户端请求的返回时间,来减少客户端无效请求的一种优化手段,其实对于客户端来说与短轮询的使用并没有本质上的区别。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">客户端发起请求后,服务端不会立即返回请求结果,而是将请求挂起等待一段时间,如果此段时间内服务端数据变更,立即响应客户端请求,若是一直无变化则等到指定的超时时间后响应请求,客户端重新发起长链接。</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-ratio="0.48143236074270557" src="/upload/6bbd33852f581e71cbdb78b2790a8e04.png" data-type="png" data-w="754" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>Nacos初识<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">为了后续演示操作方便我在本地搭了个<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">Nacos</code>。<strong style="font-weight: border;color: #0e88eb;">注意:</strong> 运行时遇到个小坑,由于<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">Nacos</code>默认是以<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">cluster</code>集群的方式启动,而本地搭建通常是单机模式<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">standalone</code>,这里需手动改一下启动脚本<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">startup.X</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 data-ratio="0.2864450127877238" src="/upload/55612c115b3785dc752af8cd3d4c1cf6.png" data-type="png" data-w="782" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">直接执行<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">/bin/startup.X</code>就可以了,默认用户密码均是<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">nacos</code>。<img data-ratio="0.4842666666666667" src="/upload/d22213b2e9219f35b26d4802471873ad.png" data-type="png" data-w="1875" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"></p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>几个概念<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;"><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">Nacos</code>配置中心的几个核心概念:<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">dataId</code>、<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">group</code>、<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">namespace</code>,它们的层级关系如下图:<img data-ratio="0.5854700854700855" src="/upload/c8726036bc49e9b26266c3913fabefb1.png" data-type="png" data-w="1404" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;"><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">dataId</code>:是配置中心里最基础的单元,它是一种<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">key-value</code>结构,<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">key</code>通常是我们的配置文件名称,比如:<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">application.yml</code>、<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">mybatis.xml</code>,而<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">value</code>是整个文件下的内容。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">目前支持<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">JSON</code>、<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">XML</code>、<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">YAML</code>等多种配置格式。<img data-ratio="0.8175257731958763" src="/upload/8e1d7454863442da06f80db2aeb46c54.png" data-type="png" data-w="970" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;"><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">group</code>:dataId配置的分组管理,比如同在dev环境下开发,但同环境不同分支需要不同的配置数据,这时就可以用分组隔离,默认分组<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">DEFAULT_GROUP</code>。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;"><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">namespace</code>:项目开发过程中肯定会有<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">dev</code>、<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">test</code>、<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">pro</code>等多个不同环境,<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">namespace</code>则是对不同环境进行隔离,默认所有配置都在<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">public</code>里。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>架构设计<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">下图简要描述了<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">nacos</code>配置中心的架构流程。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">客户端、控制台通过发送Http请求将配置数据注册到服务端,服务端持久化数据到Mysql。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">客户端拉取配置数据,并批量设置对<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">dataId</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 data-ratio="0.6542056074766355" src="/upload/a910d2a47b2d11002df8a7c9fc738758.png" data-type="png" data-w="1498" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">这里我省略了比较多的细节,如鉴权、负载均衡、高可用方面的设计(其实这部分才是真正值得学的,后边另出文讲吧),主要弄清客户端与服务端的数据交互模式。</p> <blockquote data-tool="mdnice编辑器" style="border-width: initial;border-style: none;border-color: initial;font-size: 0.9em;overflow: auto;margin-bottom: 20px;margin-top: 20px;padding-top: 10px;padding-right: 10px;padding-bottom: 10px;line-height: 1.8;border-radius: 0px 0px 10px 10px;color: rgb(14, 136, 235);background: rgb(255, 255, 255);box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> <span style="font-size: 4em;font-family: Arial, serif;line-height: 1em;font-weight: 700;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;letter-spacing: 0.1em;word-spacing: 0.2em;line-height: 26px;font-size: 15px;display: inline;">下边我们以Nacos 2.0.1版本源码分析,2.0以后的版本改动较多,和网上的很多资料略有些不同 地址:https://github.com/alibaba/nacos/releases/tag/2.0.1</p> <span style="float: right;font-size: 3em;line-height: 1em;"></span> </blockquote> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>客户端源码分析<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;"><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">Nacos</code>配置中心的客户端源码在<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">nacos-client</code>项目,其中<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">NacosConfigService</code>实现类是所有操作的核心入口。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px 1px;line-height: 1.75;letter-spacing: 0.1em;word-spacing: 0.2em;">说之前先了解个客户端数据结构<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">cacheMap</code>,这里大家重点记住它,因为它几乎贯穿了Nacos客户端的所有操作,由于存在多线程场景为保证数据一致性,<cod
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;padding: 5px;font-size: 16px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;" data-mpa-powered-by="yiban.io"> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">前言</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">对于从事java开发工作的同学来说,spring的事务肯定再熟悉不过了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">在某些业务场景下,如果一个请求中,需要同时写入多张表的数据。为了保证操作的原子性(要么同时成功,要么同时失败),避免数据不一致的情况,我们一般都会用到spring事务。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">确实,spring事务用起来贼爽,就用一个简单的注解:<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Transactional</code>,就能轻松搞定事务。我猜大部分小伙伴也是这样用的,而且一直用一直爽。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">但如果你使用不当,它也会坑你于无形。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">今天我们就一起聊聊,事务失效的一些场景,说不定你已经中招了。不信,让我们一起看看。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img data-fileid="100013339" data-ratio="0.9916666666666667" src="/upload/5ea32e18442d5829d8ed7b0088dff679.png" data-type="other" data-w="1080" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 图片 </figcaption> </figure> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">一 事务不生效</span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">1.访问权限问题</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">众所周知,java的访问权限主要有四种:private、default、protected、public,它们的权限从左到右,依次变大。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">但如果我们在开发过程中,把有某些事务方法,定义了错误的访问权限,就会导致事务功能出问题,例如:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #4078f2;line-height: 26px;">@Service</span><br><span style="color: #a626a4;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">class</span> <span style="color: #c18401;line-height: 26px;">UserService</span> </span>{<br> <br> <span style="color: #4078f2;line-height: 26px;">@Transactional</span><br> <span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">private</span> <span style="color: #a626a4;line-height: 26px;">void</span> <span style="color: #4078f2;line-height: 26px;">add</span><span style="line-height: 26px;">(UserModel userModel)</span> </span>{<br> saveData(userModel);<br> updateData(userModel);<br> }<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我们可以看到add方法的访问权限被定义成了 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">private</code>,这样会导致事务失效,spring要求被代理方法必须是 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">public</code>的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">说白了,在 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">AbstractFallbackTransactionAttributeSource</code>类的 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">computeTransactionAttribute</code>方法中有个判断,如果目标方法不是public,则 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">TransactionAttribute</code>返回null,即不支持事务。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">protected</span> TransactionAttribute <span style="color: #4078f2;line-height: 26px;">computeTransactionAttribute</span><span style="line-height: 26px;">(Method method, @Nullable Class<?> targetClass)</span> </span>{<br> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">// Don't allow no-public methods as required.</span><br> <span style="color: #a626a4;line-height: 26px;">if</span> (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {<br> <span style="color: #a626a4;line-height: 26px;">return</span> <span style="color: #a626a4;line-height: 26px;">null</span>;<br> }<br><br> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">// The method may be on an interface, but we need attributes from the target class.</span><br> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">// If the target class is null, the method will be unchanged.</span><br> Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);<br><br> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">// First try is the method in the target class.</span><br> TransactionAttribute txAttr = findTransactionAttribute(specificMethod);<br> <span style="color: #a626a4;line-height: 26px;">if</span> (txAttr != <span style="color: #a626a4;line-height: 26px;">null</span>) {<br> <span style="color: #a626a4;line-height: 26px;">return</span> txAttr;<br> }<br><br> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">// Second try is the transaction attribute on the target class.</span><br> txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());<br> <span style="color: #a626a4;line-height: 26px;">if</span> (txAttr != <span style="color: #a626a4;line-height: 26px;">null</span> && ClassUtils.isUserLevelMethod(method)) {<br> <span style="color: #a626a4;line-height: 26px;">return</span> txAttr;<br> }<br><br> <span style="color: #a626a4;line-height: 26px;">if</span> (specificMethod != method) {<br> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">// Fallback is to look at the original method.</span><br> txAttr = findTransactionAttribute(method);<br> <span style="color: #a626a4;line-height: 26px;">if</span> (txAttr != <span style="color: #a626a4;line-height: 26px;">null</span>) {<br> <span style="color: #a626a4;line-height: 26px;">return</span> txAttr;<br> }<br> <span style="color: #a0a1a7;font-style: italic;line-height: 26px;">// Last fallback is the class of the original method.</span><br> txAttr = findTransactionAttribute(method.getDeclaringClass());<br> <span style="color: #a626a4;line-height: 26px;">if</span> (txAttr != <span style="color: #a626a4;line-height: 26px;">null</span> && ClassUtils.isUserLevelMethod(method)) {<br> <span style="color: #a626a4;line-height: 26px;">return</span> txAttr;<br> }<br> }<br> <span style="color: #a626a4;line-height: 26px;">return</span> <span style="color: #a626a4;line-height: 26px;">null</span>;<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">也就是说,如果我们自定义的事务方法(即目标方法),它的访问权限不是 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">public</code>,而是private、default或protected的话,spring则不会提供事务功能。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">2. 方法用final修饰</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">有时候,某个方法不想被子类重新,这时可以将该方法定义成final的。普通方法这样定义是没问题的,但如果将事务方法定义成final,例如:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #4078f2;line-height: 26px;">@Service</span><br><span style="color: #a626a4;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">class</span> <span style="color: #c18401;line-height: 26px;">UserService</span> </span>{<br><br> <span style="color: #4078f2;line-height: 26px;">@Transactional</span><br> <span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">public</span> <span style="color: #a626a4;line-height: 26px;">final</span> <span style="color: #a626a4;line-height: 26px;">void</span> <span style="color: #4078f2;line-height: 26px;">add</span><span style="line-height: 26px;">(UserModel userModel)</span></span>{<br> saveData(userModel);<br> updateData(userModel);<br> }<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我们可以看到add方法被定义成了 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">final</code>的,这样会导致事务失效。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">为什么?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">如果你看过spring事务的源码,可能会知道spring事务底层使用了aop,也就是通过jdk动态代理或者cglib,帮我们生成了代理类,在代理类中实现的事务功能。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">但如果某个方法用final修饰了,那么在它的代理类中,就无法重写该方法,而添加事务功能。</p> <blockquote data-tool="mdnice编辑器" style="border-width: initial;border-style: none;border-color: initial;font-size: 0.9em;overflow: auto;margin-bottom: 20px;margin-top: 20px;padding-top: 15px;padding-right: 10px;padding-bottom: 15px;line-height: 1.75;border-radius: 13px;color: rgb(53, 53, 53);background: rgb(245, 245, 245);"> <span style="display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;font-size: 16px;margin-right: 10px;margin-left: 10px;">注意:如果某个方法是static的,同样无法通过动态代理,变成事务方法。</p> <span style="float: right;display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">”</span> </blockquote> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">3.方法内部调用</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">有时候我们需要在某个Service类的某个方法中,调用另外一个事务方法,比如:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #4078f2;line-height: 26px;">@Service</span><br><span style="color: #a626a4;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">class</span> <span style="color: #c18401;line-height: 26px;">UserService</span> </span>{<br><br> <span style="color: #4078f2;line-height: 26px;">@Autowired</span><br> <span style="color: #a626a4;line-height: 26px;">private</span> UserMapper userMapper;<br><br><br> <span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">public</span> <span style="color: #a626a4;line-height: 26px;">void</span> <span style="color: #4078f2;line-height: 26px;">add</span><span style="line-height: 26px;">(UserModel userModel)</span> </span>{<br> userMapper.insertUser(userModel);<br> updateStatus(userModel);<br> }<br><br> <span style="color: #4078f2;line-height: 26px;">@Transactional</span><br> <span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">public</span> <span style="color: #a626a4;line-height: 26px;">void</span> <span style="color: #4078f2;line-height: 26px;">updateStatus</span><span style="line-height: 26px;">(UserModel userModel)</span> </span>{<br> doSameThing();<br> }<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我们看到在事务方法add中,直接调用事务方法updateStatus。从前面介绍的内容可以知道,updateStatus方法拥有事务的能力是因为spring aop生成代理了对象,但是这种方法直接调用了this对象的方法,所以updateStatus方法不会生成事务。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">由此可见,在同一个类中的方法直接内部调用,会导致事务失效。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">那么问题来了,如果有些场景,确实想在同一个类的某个方法中,调用它自己的另外一个方法,该怎么办呢?</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>3.1 新加一个Service方法<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这个方法非常简单,只需要新加一个Service方法,把<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Transactional</code>注解加到新Service方法上,把需要事务执行的代码移到新方法中。具体代码如下:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #4078f2;line-height: 26px;">@Servcie</span><br><span style="color: #a626a4;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">class</span> <span style="color: #c18401;line-height: 26px;">ServiceA</span> </span>{<br> <span style="color: #4078f2;line-height: 26px;">@Autowired</span><br> prvate ServiceB serviceB;<br><br> <span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">public</span> <span style="color: #a626a4;line-height: 26px;">void</span> <span style="color: #4078f2;line-height: 26px;">save</span><span style="line-height: 26px;">(User user)</span> </span>{<br> queryData1();<br> queryData2();<br> serviceB.doSave(user);<br> }<br>}<br><br><span style="color: #4078f2;line-height: 26px;">@Servcie</span><br><span style="color: #a626a4;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">class</span> <span style="color: #c18401;line-height: 26px;">ServiceB</span> </span>{<br><br> <span style="color: #4078f2;line-heigh
作者:じ☆ve不哭
## 查看CPU相关命令 ``` #限制某个线程的cpu使用率 sudo cpulimit -p pid -l 50 ps -eo %cpu,args | grep -m1 PROCESS | awk '{print $1}' #将当前进程按照memory和cpu排序 ps aux --sort=%mem,%cpu #按照cpu使用率排序 ps -e -o pcpu,cpu,nice,state,cputime,args --sort pcpu | sed "/^ 0.0 /d" #查看当前系统的物理cpu个数 grep "processor" /proc/cpuinfo | wc -l grep -c -e '^cpu[0-9]\+' /proc/stat #查看当前cpu型号 grep "model name" /proc/cpuinfo #查看当前cpu信息 cat /proc/cpuinfo #查看当前系统的位数 grep -q '\<lm\>' /proc/cpuinfo && echo 64 bits || echo 32 bits getconf LONG_BIT | grep '64' java -version #查看当前系统的cpu频率 awk -F": " '/cpu MHz\ */ { print "Processor (or core) running speed is: " $2 }' /proc/cpuinfo ; dmidecode | awk -F": " '/Current Speed/ { print "Processor real speed is: " $2 }' #查看每个cpu每个进程的cpu使用率 ps ax -L -o pid,tid,psr,pcpu,args | sort -nr -k4| head -15 | cut -c 1-90 #查看当前中断 cat /proc/interrupts #查看多个处理器的使用率相关信息 mpstat –P ALL 1 #每个物理CPU中Core的个数: cat /proc/cpuinfo | grep "cpu cores" | uniq | awk -F: '{print $2}' #是否为超线程? #如果有两个逻辑CPU具有相同的”core id”,那么超线程是打开的。 #每个物理CPU中逻辑CPU(可能是core, threads或both)的个数: cat /proc/cpuinfo | grep "siblings" #/proc/stat 文件中有一行记录的机器从启动依赖,各个中断序号发生中断的次数。 #这一行以intr开头,接下来的第一个数字是总的中断数目,之后就是分别的中断数目,从0开始。 cat /proc/stat | grep intr ``` ## 查找文件相关命令 ``` #按照目录大小排序战士最前面15个目录或者文件 du -xB M --max-depth=2 /var | sort -rn | head -n 15 #列出当前所有子目录的文件大小 du -h --max-depth=1 #列出当前文件或者目录最大的10个 du -s * | sort -n | tail #按照目录大小从大到小排序 du -b --max-depth 1 | sort -nr | perl -pe 's{([0-9]+)}{sprintf "%.1f%s", $1>=2**30? ($1/2**30, "G"): $1>=2**20? ($1/2**20, "M"): $1>=2**10? ($1/2**10, "K"): ($1, "")}e' #列出path这个目录的文件树 du -h /path | sort -h #每隔60s监控对应目录的文件大小变化 watch -n60 du /var/log/messages #递归删除当前目录下所有子目录中的.svn目录 find . -type d -name '.svn' -print0 | xargs -0 rm -rdf #列出当前磁盘的使用情况 df -P | column -t #监控磁盘的使用情况 watch -d -n 5 df #列出当前inode的使用情况 df -i <partition> #按照每个磁盘使用量从高到低排序 df -h | grep -v ^none | ( read header ; echo "$header" ; sort -rn -k 5) #查看物理磁盘的使用情况 df -x tmpfs | grep -vE "(gvfs|procbususb|rootfs)" #查看当前所有磁盘的大小和使用量 df -H #查看所有分区使用情况 fdisk -l /dev/sda # 显示系统所有的分区或给定的分区 fdisk -l # 显示时,显示的是扇区数不是柱面数 fdisk -u # 显示指定partition的block数 fdisk -s partition #查看磁盘的读写容量 iostat -m -d /dev/sda1 #测试磁盘的读写速度 hdparm -t /dev/sda #查看某个文件的所有链接 find -L / -samefile /path/to/file -exec ls -ld {} + #查看最大的5个文件 find . -type f -exec ls -s {} \; | sort -n -r | head -5 #查看365天前的文件并删除 find ./ -type f -mtime +365 -exec rm -f {} \; #查看大于100M的文件 find . -type f -size +100M ```
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;" data-mpa-powered-by="yiban.io"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">最近给新人code review,差点吐血,也有一些调优方面的知识,所以顺便记录了下来分享给大家。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这里的主要是分享索引方面的调优,在工作中,很多同学都有建立索引的一些经验,但是是否有自己深入的思考过,怎么样建立索引才最合适。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">字符串怎么建立索引、怎么优化联合索引、怎么避免回表等一些问题,是否有结合自己的实际项目进行深入的思考呢?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这里,我就将自己实际中遇到的一些问题分享给大家,下面开始我们的正题,首先开始之前,先来回顾一些基础的知识。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">什么是Mysql的索引,联合索引是什么?回表是什么?回表怎么解决?</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>Mysql索引</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">Mysql的索引是一种加快查询速度的数据结构,索引就好比书的目录一样能够快速的定位你要查找的位置。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">Mysql的索引底层是使用B+树的数据结构进行实现,结构如下图所示:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><img data-ratio="0.45885634588563456" src="/upload/dac85735f13b5c48fb188c9313669781.png" data-type="png" data-w="717" style="display: block;margin-right: auto;margin-left: auto;">索引的一个数据页的大小是16kb,从磁盘加载到内存中是以数据页的大小为单位进行加载,然后供查询操作进行查询,若是查询的数据不在内存中,才会从磁盘中再次加载到内存中。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">索引的实现有很多,比如hash。hash是以key-value的形式进行存储,适合于等值查询的场景,查询的时间复杂度为O(1),因为hash储存并不是有序的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">所以,对于范围查询就可能要遍历所有数据进行查询,而且不同值的计算还会出现hash冲突,所以hash并不适合于做Mysql的索引。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">有序数组在等值查询和范围查询性能都是非常好的,那为什么又不用有序数组作为索引呢?因为对于数组而言作为索引更新的成本太高,新增数据要把后面的数据都往后移一位,所以也不采用有序数组作为索引的底层实现。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">最后二叉树,主要是因为二叉树只有二叉,一个节点存储的数据量非常有限,需要频繁的随机IO读写磁盘,若是数据量大的情况下二叉的树高太高,严重影响性能,所以也不采用二叉树进行实现。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">而B+树是多叉树,一个数据页的大小是16kb,在1-3的树高就能存储10亿级以上的数据,也就是只要访问磁盘1-3次就足够了,并且B+树的叶子结点上一个叶子结点有指针指向下一个叶子结点,便于范围查询:</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-ratio="0.16073478760045926" src="/upload/9fcc256e0ad4d1becd0618ad627771c8.png" data-type="png" data-w="871" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>种类的索引<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">索引从数据结构进行划分的分为:<strong>B+树索引、hash索引、R-Tree索引、FULLTEXT索引</strong>。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">索引从物理存储的角度划分为:<strong>聚族索引和非聚族索引</strong>。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">从逻辑的角度分为:<strong>主键索引、普通索引、唯一索引、联合索引以及空间索引</strong>。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>什么是回表</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">再详细了解什么事回表之前,我们先来详细的深入了解一下什么是InnoDB的索引存储形式,InnoDB的主键索引存储形式是聚族索引,索引与数据都在一起:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><img data-ratio="0.47155361050328226" src="/upload/8165313d66196b105d9e65a38eb7a9e8.png" data-type="png" data-w="914" style="display: block;margin-right: auto;margin-left: auto;">InnoDB的主键索引中叶子结点并不是存储行指针,而是存储行数据,二级索引中MyISAM也是一样的存储方式,InnoDB的二级索引的叶子结点则是存储当前索引值以及对应的主键索引值。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">InnoDB的二级索引带来的好处就是减少了由于数据移动或者数据页分列导致行数据的地址变了而带来的维护二级索引的性能开销,因为InnoDB的二级索引不需要更新行指针:</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-ratio="0.8545647558386412" src="/upload/416d4c2d4c2c4d2a3a71529695511104.png" data-type="png" data-w="942" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">上面说到InnoDB引擎的主键索引存储的是行数据,二级索引的叶子结点存储的是索引数据以及对应的主键,所以回表就是根据索引进行条件查询,回到主键索引树进行搜索的过程:</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-ratio="0.5545243619489559" src="/upload/38172f1be4fabae8b29e710974b58cd1.png" data-type="png" data-w="431" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">因为查询还要回表一次,再次查询主键索引树,所以实际中应该尽量避免回表的产生。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="display: none;"></span>解决回表<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">解决回表问题可以建立联合索引进行索引覆盖,如图所示根据name字段查询用户的name和sex属性出现了回表问题:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><img data-ratio="0.5545243619489559" src="/upload/38172f1be4fabae8b29e710974b58cd1.png" data-type="png" data-w="431" style="display: block;margin-right: auto;margin-left: auto;">那么我们可以建立下面这个联合索引来解决:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/eTBFF2uBxbB09NejRBetGLudXvfc74iaMBSo9iciaOuHkjX3fmhD1wczK5Lc1DjSJVsYjPlopCzb9Yq2hLM63t9KuHCUNxpm30N/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #272822;border-radius: 5px;">create table user (<br> id int primary key,<br> name varchar(20),<br> sex varchar(5),<br> index(name, sex)<br>) engine = innodb;<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">建立了如上所示的index(name,sex)联合索引,在二级索引的叶子结点的位置就会同时也出现sex字段的值,因为能够获取到要查询的所有字段,因为就不用再回表查询一次。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>最左前缀原则</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">最左前缀原则可以是联合索引的的最左N个字段,也可以是字符串索引的最左的M个字符。举个例子,假如现在有一个表的原始数据如下所示:</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-ratio="1.0059171597633136" src="/upload/f22b8ed5003d6fcd936d5ccb723b995b.png" data-type="png" data-w="169" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">并根据col3 ,col2的顺序建立联合索引,此时联合索引树结构如图下所示:</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-ratio="0.4329073482428115" src="/upload/a88fd445e566a02cc38a9b5303a84a19.png" data-type="png" data-w="626" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">叶子结点中首先会根据col3的字符进行排序,若是col3相等,在col3相等的值里面再对col2进行排序,假如我们要查询where col3 like 'Eri%',就可以快速的定位查询到Eric。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">若是查询条件为where col3 like '%se',前面的字符不确定,表示任意字符都可以,这样就可以导致全表扫描进行字符的比较,就会使索引失效。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>调优案例一</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">其中第一个案例新人写了一个这样的sql,由于业务的原因就不粘贴全部sql,其中sql的条件如下所示<strong>WHERE ( STATUS = '1' AND shop_code = 'XXX' ) GROUP BY act_id</strong>。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">并且他在表中建立的这样的一个索引<strong>idx_status_shop_code</strong>,当时看到就吐血一地。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">我给新人提出建议是把shop_code为''空字符串的(数据库默认值)是设为一个特殊的00000这样的类型,不要把商店的shop_code默认值设置为空字符串。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">并且,索引中shop_code字段放在前面,建<strong>idx_shop_code_status_act_id</strong>索引。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>因为一般状态值status只有0和1,区分度不大,而shop_code的区分度大,在执行where条件筛选的时候,区分度大的放在前面,第一层过滤的时候就能过滤掉大部分行数,减少扫描的行数,提高效率。</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">并且将act_id,和store_code也加入其中,sql中涉及分组(group by)操作,这样就能避免filesort排序,因为索引本来就是有序的:</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-ratio="0.18888144675150703" src="/upload/f4ec1dd9588c344b18bdd2cae7373a79.png" data-type="png" data-w="1493" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">并且从他的sql中可以看到他只要返回act_id,而实际中只用到了act_id,所以将act_id也加入索引中就可以避免回表的操作,所以再索引中最后加入act_id有两大好处:<strong>避免回表以及避免filesort排序</strong>。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">因为写sql的不良习惯造成回表操作,平时也没有注意建立索引的一些原则,以及理解索引的一些原理,所以新人对于一些优化的理解还有要一步一步的指导,毕竟自己也是从新人过来的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">对于索引的顺序的建立,以及出现filesort的解决方案在阿里的开发手册中也有提到:</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-ratio="0.2144469525959368" src="/upload/8d75ecb07ec6288009acd3846410ce5e.png" data-type="png" data-w="886" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">order by和group by都可以利用索引的有序性。</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-ratio="0.17361894024802707" src="/upload/abbe70df0a66dbc1df07a9847e626101.png" data-type="png" data-w="887" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">说真的这本开发手册还是非常好用的,里面很多经验总结,慢慢的遇到场景就能够瞬间顿悟,毕竟是众多阿里人的开发经验的结晶。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>调优案例二</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">第二个案例是关于字符串的,新人接到一个需求需要比较电话,但是一般电话在数据库中都会加密md5。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">所以,新人为了提高查询的效率新建KEY <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">idx_mobile_md5_type</code> (<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">mobile_md5</code>,<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">type</code>)使用md5全字段建立索引。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">我是建议他使用<strong>select count(distinct left(mobile_md5, 5))/count(*) from XXX.users</strong>查找最大的区分度:</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-ratio="0.17016574585635358" src="/upload/ca3dc8d4de937c24b06004d664bd531d.png" data-type="png" data-w="905" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">在实际中当md5值长度为5以及大于5的长度都不变了:</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-ratio="0.1670235546038544" src="/upload/4e36dccabed84827ee5feaa0c264eb32.png" data-type="png" data-w="934" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">实际情况只要前五个字符就能达到80%的区分度,并且再加字段长度区分度也不变,所以个人提出只要建立前五个字符的索引即可,可以大大节约空间。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这个在阿里的开发手册也有提到,其实一般来说达到90%的区分度是比较好的,区分度越大,就类似于越趋向于唯一索引,过滤的行数就越多:</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-ratio="0.35033259423503327" src="/upload/c48ccb9af6fec1121ff9b1b77b76352f.png" data-type="png" data-w="902" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>调优案例三</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">最后一个字符串的案例就是userId,这个userId使用有20位的长度的字符串左右,有点类似于身份证号码,大家都知道身份证号码的前多少位是基本一样的,区别大的在后面的几位(具体几位没去了解过)。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">我们这边的场景也是一样,userId前10位左右基本都是一样,反而只有后面的几位区别度高达90%以上。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">所以,建议新人建立userId的反转之后的前几位索引即可,区别度可以通过:<strong>select count(distinct left(REVERSE(userId), 7))/count(*) as '区分度' from XXX.users;</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">具体sql如下的sql:<strong>select u.city_code from XXX.city_role_user u where role_key = 'XXX' and uc_id = 'XXX' and status = 1;</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这个sql有两个问题,一个是把区分度不大的role_key放在前面,因为一般角色key在PC端只有几种,区别度很小;另一个就是前面说的uc_id字符串问题。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">我是建议把where条件的条件uc_id放在前面,建立索引也是如此,并且uc_id是由20位的数字组成,前面的10位左右都是一样的,只有后面的几位区分度才大。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">所以个人也建议通过查询区分度,并且建立翻转字符串后的索引来达到节省空间,并且还可以提升查询效率,最后就是city_code也加入索引中建立联合索引就可以避免回表操作。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">所以,这就要sql优化的关键点有三个:<strong>区分度大的放在前面、字符串减少长度、避免回表</strong>。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 22px;"><span style="display: none;"></span>其它的code review</h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">通过code review新人的代码,还发现一些问题,就是不遵循接口的单一原则,比较喜欢写通用的接口,一个接口多个场景使用,通常使用select * 返回数据,对于一些where条件的查询需要大量的回表操作,但是一些接口中只需要用到其中select 回来的一个字段,所以导致慢sql,慢接口的产生。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">并且,在实际的编码中主要是面向于实现,对于一些整体的模块没有把控,类似于一些可以使用到<strong>策略模式、建造者模式</strong>等设计模式的,都没有使用,代码的扩展性比较差。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">还要在代码中大量的使用Java 8的stream流操作,代码的可读性差,对于stream流其实可以用来并行流处理还是挺高效的,因为stream流的底层使用到了Fork/Join。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">在服务器配置允许的条件下,使用如下代码,数据量大的时候是可以有效率提升的,下面引用redspider的一个案例:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/eTBFF2uBxbB09NejRBetGLudXvfc74iaMBSo9iciaOuHkjX3fmhD1wczK5Lc1DjSJVsYjPlopCzb9Yq2hLM63t9KuHCUNxpm30N/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #272822;border-radius: 5px;">public class StreamParallelDemo {<br> public static void main(String[] args) {<br> System.out.println(String.format(<span style="color: #a6e22e;line-height: 26px;">"本计算机的核数:%d"</span>, Runtime.getRuntime().availableProcessors()));<br><br> // 产生100w个随机数(1 ~ 100),组成列表<br> Random random = new Random();<br> List<Integer> list = new ArrayList<>(1000_0000);<br><br> <span style="color: #f92672;font-weight: bold;line-height: 26px;">for</span> (int i = 0; i < 1000_0000; i++) {<br> list.add(random.nextInt(100));<br> }<br><br> long prevTime = getCurrentTime();<br> list.stream().reduce((a, b) -> a + b).ifPresent(System.out::println);<br> System.out.println(String.format(<span style="color: #a6e22e;line-height: 26px;">"单线程计算耗时:%d"</span>, getCurrentTime() - prevTime));<br><br> prevTime = getCurrentTime();<br> list.stream().parallel().reduce((a, b) -> a + b).ifPresent(System.out::println);<br> System.out.println(String.format(<span style="color: #a6e22e;line-height: 26px;">"多线程计算耗时:%d"</span>, getCurrentTime() - prevTime));<br><br> }<br><br> private static long <span style="line-height: 26px;"><span style="color: #a6e22e;font-weight: bold;line-height: 26px;">getCurrentTime</span></span>() {<br> <span style="color: #a6e22e;line-height: 26px;">return</span> System.currentTimeMillis();<br> }<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">一路code review,发现还是挺多问题,也是非常基础的东西,这里就顺手做了个记录,不过也情有可原,毕竟是新人,只能慢慢的指导,一行代码一行代码的手把手教。</p> <section class="mp_profile_iframe_wrp"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="MzU1MzE4OTU0OQ==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg4C0ZCBNbxUJHUC82nmVsFT2Vnxf3Wb2cWyy9tl4ciafSCKcKINW0JVhwyaM5pHQlEdIrnSNDNd0Q/0?wx_fmt=png" data-nickname="黎杜编程" data-alias="LDCldc123095" data-signature="专注Java技术文章输出100年" data-from="0"></mpprofile> </section> </section>