文章列表

Spring Boot 插件化开发模式

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;padding: 5px;font-size: 16px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;" data-mpa-powered-by="yiban.io"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">大家好,我是不才陈某~</span></p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;">一、前言</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">插件化开发模式正在很多编程语言或技术框架中得以广泛的应用实践,比如大家熟悉的jenkins,docker可视化管理平台rancher,以及日常编码使用的编辑器idea,vscode等,随处可见的带有热插拔功能的插件,让系统像插了翅膀一样,大大提升了系统的扩展性和伸缩性,也拓展了系统整体的使用价值,那么为什么要使用插件呢?</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;">1.1 使用插件的好处</span><span style="display: none;"></span></h3> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>1.1.1 模块解耦<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;">实现服务模块之间解耦的方式有很多,但是插件来说,其解耦的程度似乎更高,而且更灵活,可定制化、个性化更好。</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>1.1.2 提升扩展性和开放性<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;">以spring来说,之所以具备如此广泛的生态,与其自身内置的各种可扩展的插件机制是分不开的,试想为什么使用了spring框架之后可以很方便的对接其他中间件,那就是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;">插件化机制让系统的扩展性得以提升,从而可以丰富系统的周边应用生态。</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>1.1.3 方便第三方接入<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;">有了插件之后,第三方应用或系统如果要对接自身的系统,直接基于系统预留的插件接口完成一套适合自己业务的实现即可,而且对自身系统的侵入性很小,甚至可以实现基于配置参数的热加载,方便灵活,开箱即用。</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;">1.2 插件化常用实现思路</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为例,这里结合实际经验,整理一些常用的插件化实现思路:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> spi机制; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 约定配置和目录,利用反射配合实现; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> springboot中的Factories机制; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> java agent(探针)技术; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> spring内置扩展点; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 第三方插件包,例如:spring-plugin-core; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> spring aop技术; </section></li> </ul> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;">二、Java常用插件实现方案</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;">2.1 serviceloader方式</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;">serviceloader是java提供的spi模式的实现。按照接口开发实现类,而后配置,java通过ServiceLoader来实现统一接口不同实现的依次调用。而java中最经典的serviceloader的使用就是Java的spi机制。</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>2.1.1 java spi<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;">SPI全称 Service Provider Interface ,是JDK内置的一种服务发现机制,SPI是一种动态替换扩展机制,比如有个接口,你想在运行时动态给他添加实现,你只需按照规范给他添加一个实现类即可。比如大家熟悉的jdbc中的Driver接口,不同的厂商可以提供不同的实现,有mysql的,也有oracle的,而Java的SPI机制就可以为某个接口寻找服务的实现。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">下面用一张简图说明下SPI机制的原理</p> <p><img class="rich_pages wxw-img" data-ratio="0.3431603773584906" data-type="png" data-w="848" style="height: auto !important;" src="/upload/9d42cdd05b9ec4ea4d0d38ca2df60c21.png"></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>2.1.2 java spi 简单案例<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;">如下工程目录,在某个应用工程中定义一个插件接口,而其他应用工程为了实现这个接口,只需要引入当前工程的jar包依赖进行实现即可,这里为了演示我就将不同的实现直接放在同一个工程下;</p> <p><img class="rich_pages wxw-img" data-ratio="0.9521178637200737" data-type="png" data-w="543" style="height: auto !important;" src="/upload/21f6bf405c1bcbac2dd75b7cc3897d2e.png"></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;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQezibPc5DoAQ8wjtcJc0svthOVD7uzKFmIQtjO6Drbj7c1PwLLFpPMSQ2LEj04Keibp0GFxFXEYb1T/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">interface</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">MessagePlugin</span>&nbsp;</span>{<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;String&nbsp;<span style="color: #1c00cf;line-height: 26px;">sendMsg</span><span style="color: #5c2699;line-height: 26px;">(Map&nbsp;msgMap)</span></span>;<br>&nbsp;<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">定义两个不同的实现</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQezibPc5DoAQ8wjtcJc0svthOVD7uzKFmIQtjO6Drbj7c1PwLLFpPMSQ2LEj04Keibp0GFxFXEYb1T/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">class</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">AliyunMsg</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">implements</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">MessagePlugin</span>&nbsp;</span>{<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@Override</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;String&nbsp;<span style="color: #1c00cf;line-height: 26px;">sendMsg</span><span style="color: #5c2699;line-height: 26px;">(Map&nbsp;msgMap)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span style="color: #c41a16;line-height: 26px;">"aliyun&nbsp;sendMsg"</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">return</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">"aliyun&nbsp;sendMsg"</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">class</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">TencentMsg</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">implements</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">MessagePlugin</span>&nbsp;</span>{<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@Override</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;String&nbsp;<span style="color: #1c00cf;line-height: 26px;">sendMsg</span><span style="color: #5c2699;line-height: 26px;">(Map&nbsp;msgMap)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span style="color: #c41a16;line-height: 26px;">"tencent&nbsp;sendMsg"</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">return</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">"tencent&nbsp;sendMsg"</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<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;">在resources目录按照规范要求创建文件目录,并填写实现类的全类名</p> <p><img class="rich_pages wxw-img" data-ratio="0.2550693703308431" data-type="png" data-w="937" style="height: auto !important;" src="/upload/8054556f03745af112f9efba01274f64.png"></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">自定义服务加载类</span></p> <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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQezibPc5DoAQ8wjtcJc0svthOVD7uzKFmIQtjO6Drbj7c1PwLLFpPMSQ2LEj04Keibp0GFxFXEYb1T/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;">&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">static</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">void</span>&nbsp;<span style="color: #1c00cf;line-height: 26px;">main</span><span style="color: #5c2699;line-height: 26px;">(String[]&nbsp;args)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServiceLoader&lt;MessagePlugin&gt;&nbsp;serviceLoader&nbsp;=&nbsp;ServiceLoader.load(MessagePlugin<span style="line-height: 26px;">.<span style="color: #aa0d91;line-height: 26px;">class</span>)</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&lt;MessagePlugin&gt;&nbsp;iterator&nbsp;=&nbsp;serviceLoader.iterator();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map&nbsp;map&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;HashMap();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">while</span>&nbsp;(iterator.hasNext()){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessagePlugin&nbsp;messagePlugin&nbsp;=&nbsp;iterator.next();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;messagePlugin.sendMsg(map);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<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;">运行上面的程序后,可以看到下面的效果,这就是说,使用ServiceLoader的方式可以加载到不同接口的实现,业务中只需要根据自身的需求,结合配置参数的方式就可以灵活的控制具体使用哪一个实现。</p> <p><img class="rich_pages wxw-img" data-ratio="0.21666666666666667" data-type="png" data-w="600" style="height: auto !important;" src="/upload/bc2d7323c7f7a70d2a848d8a783c1774.png"></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.2 自定义配置约定方式</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;">serviceloader其实是有缺陷的,在使用中必须在META-INF里定义接口名称的文件,在文件中才能写上实现类的类名,如果一个项目里插件化的东西比较多,那很可能会出现越来越多配置文件的情况。关注公众号:码猿技术专栏,回复关键词:1111 获取阿里内部Java性能调优手册!所以在结合实际项目使用时,可以考虑下面这种实现思路:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> A应用定义接口; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> B,C,D等其他应用定义服务实现; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> B,C,D应用实现后达成SDK的jar; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> A应用引用SDK或者将SDK放到某个可以读取到的目录下; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> A应用读取并解析SDK中的实现类; </section></li> </ul> <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>2.2.1 添加配置文件<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;">在配置文件中,将具体的实现类配置进去</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQezibPc5DoAQ8wjtcJc0svthOVD7uzKFmIQtjO6Drbj7c1PwLLFpPMSQ2LEj04Keibp0GFxFXEYb1T/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #836C28;line-height: 26px;">server&nbsp;:</span><br>&nbsp;&nbsp;<span style="color: #836C28;line-height: 26px;">port&nbsp;:</span>&nbsp;<span style="color: #1c00cf;line-height: 26px;">8081</span><br><span style="color: #836C28;line-height: 26px;">impl:</span><br>&nbsp;&nbsp;<span style="color: #836C28;line-height: 26px;">name&nbsp;:</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">com.congge.plugins.spi.MessagePlugin</span><br>&nbsp;&nbsp;<span style="color: #836C28;line-height: 26px;">clazz&nbsp;:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #1c00cf;line-height: 26px;">-</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">com.congge.plugins.impl.TencentMsg</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #1c00cf;line-height: 26px;">-</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">com.congge.plugins.impl.AliyunMsg</span><br></code></pre> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>2.2.2 自定义配置文件加载类<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;">通过这个类,将上述配置文件中的实现类封装到类对象中,方便后续使用;</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQezibPc5DoAQ8wjtcJc0svthOVD7uzKFmIQtjO6Drbj7c1PwLLFpPMSQ2LEj04Keibp0GFxFXEYb1T/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #aa0d91;line-height: 26px;">import</span>&nbsp;lombok.Getter;<br><span style="color: #aa0d91;line-height: 26px;">import</span>&nbsp;lombok.Setter;<br><span style="color: #aa0d91;line-height: 26px;">import</span>&nbsp;lombok.ToString;<br><span style="color: #aa0d91;line-height: 26px;">import</span>&nbsp;org.springframework.boot.context.properties.ConfigurationProperties;<br><span style="color: #643820;line-height: 26px;">@ConfigurationProperties</span>(<span style="color: #c41a16;line-height: 26px;">"impl"</span>)<br><span style="color: #643820;line-height: 26px;">@ToString</span><br><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">class</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">ClassImpl</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@Getter</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@Setter</span><br>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;name;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@Getter</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@Setter</span><br>&nbsp;&nbsp;&nbsp;&nbsp;String[]&nbsp;clazz;<br>}<br></code></pre> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>2.2.3 自定义测试接口<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;">使用上述的封装对象通过类加载的方式动态的在程序中引入</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQezibPc5DoAQ8wjtcJc0svthOVD7uzKFmIQtjO6Drbj7c1PwLLFpPMSQ2LEj04Keibp0GFxFXEYb1T/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #aa0d91;line-height: 26px;">import</span>&nbsp;com.congge.config.ClassImpl;<br><span style="color: #aa0d91;line-height: 26px;">import</span>&nbsp;com.congge.plugins.spi.MessagePlugin;<br><span style="color: #aa0d91;line-height: 26px;">import</span>&nbsp;org.springframework.beans.factory.annotation.Autowired;<br><span style="color: #aa0d91;line-height: 26px;">import</span>&nbsp;org.springframework.web.bind.annotation.GetMapping;<br><span style="color: #aa0d91;line-height: 26px;">import</span>&nbsp;org.springframework.web.bind.annotation.RestController;<br>&nbsp;<br><span style="color: #aa0d91;line-height: 26px;">import</span>&nbsp;java.util.HashMap;<br>&nbsp;<br><span style="color: #643820;line-height: 26px;">@RestController</span><br><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">class</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">SendMsgController</span>&nbsp;</span>{<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@Autowired</span><br>&nbsp;&nbsp;&nbsp;&nbsp;ClassImpl&nbsp;classImpl;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//localhost:8081/sendMsg</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@GetMapping</span>(<span style="color: #c41a16;line-height: 26px;">"/sendMsg"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;String&nbsp;<span style="color: #1c00cf;line-height: 26px;">sendMsg</span><span style="color: #5c2699;line-height: 26px;">()</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">throws</span>&nbsp;Exception</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">for</span>&nbsp;(<span style="color: #aa0d91;line-height: 26px;">int</span>&nbsp;i=<span style="color: #1c00cf;line-height: 26px;">0</span>;i&lt;classImpl.getClazz().length;i++)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;pluginClass=&nbsp;Class.forName(classImpl.getClazz()[i]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessagePlugin&nbsp;messagePlugin&nbsp;=&nbsp;(MessagePlugin)&nbsp;pluginClass.newInstance();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;messagePlugin.sendMsg(<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;HashMap());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">return</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">"success"</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;<br>}<br></code></pre> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;"><span style="display: none;"></span>2.2.4 启动类<span style="display: none;"></span></h4> <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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQezibPc5DoAQ8wjtcJc0svthOVD7uzKFmIQtjO6Drbj7c1PwLLFpPMSQ2LEj04Keibp0GFxFXEYb1T/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #643820;line-height: 26px;">@EnableConfigurationProperties</span>({ClassImpl<span style="line-height: 26px;">.<span style="color: #aa0d91;line-height: 26px;">class</span>})<br>@<span style="color: #5c2699;line-height: 26px;">SpringBootApplication</span><br><span style="color: #5c2699;line-height: 26px;">public</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">class</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">PluginApp</span>&nbsp;</span>{<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">static</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">void</span>&nbsp;<span style="color: #1c00cf;line-height: 26px;">main</span><span style="color: #5c2699;line-height: 26px;">(String[]&nbsp;args)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SpringApplication.run(PluginApp<span style="line-height: 26px;">.<span style="color: #aa0d91;line-height: 26px;">class</span>,<span style="color: #5c2699;line-height: 26px;">args</span>)</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;<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: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">localhost:8081/sendMsg</code>,在控制台中可以看到下面的输出信息,即通过这种方式也可以实现类似serviceloader的方式,不过在实际使用时,可以结合配置参数进行灵活的控制;</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.19119496855345913" data-type="png" data-w="795" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/9cefb2a099818a8fe87e473c92850b34.png"> </figure> <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.3 自定义配置读取依赖jar的方式</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;">更进一步,在很多场景下,可能我们并不想直接在工程中引入接口实现的依赖包,这时候可以考虑通过读取指定目录下的依赖jar的方式,利用反射的方式进行动态加载,这也是生产中一种比较常用的实践经验。</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> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 应用A定义服务接口; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 应用B,C,D等实现接口(或者在应用内部实现相同的接口); </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 应用B,C,D打成jar,放到应用A约定的读取目录下; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 应用A加载约定目录下的jar,通过反射加载目标方法; </section></li> </ul> <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>2.3.1 创建约定目录<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;">在当前工程下创建一个lib目录,并将依赖的jar放进去</p> <p><img class="rich_pages wxw-img" data-ratio="0.603125" data-type="png" data-w="320" style="height: auto !important;" src="/upload/5367fd13839040a8ad8a9f87071ae8ca.png"></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>2.3.2 新增读取jar的工具类<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;">添加一个工具类,用于读取指定目录下的jar,并通过反射的方式,结合配置文件中的约定配置进行反射方法的执行;</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQezibPc5DoAQ8wjtcJc0svthOVD7uzKFmIQtjO6Drbj7c1PwLLFpPMSQ2LEj04Keibp0GFxFXEYb1T/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #643820;line-height: 26px;">@Component</span><br><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">class</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">ServiceLoaderUtils</span>&nbsp;</span>{<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@Autowired</span><br>&nbsp;&nbsp;&nbsp;&nbsp;ClassImpl&nbsp;classImpl;<br>&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">static</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">void</span>&nbsp;<span style="color: #1c00cf;line-height: 26px;">loadJarsFromAppFolder</span><span style="color: #5c2699;line-height: 26px;">()</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">throws</span>&nbsp;Exception&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;path&nbsp;=&nbsp;<span style="color: #c41a16;line-height: 26px;">"E:\\code-self\\bitzpp\\lib"</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;f&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;File(path);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>&nbsp;(f.isDirectory())&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">for</span>&nbsp;(File&nbsp;subf&nbsp;:&nbsp;f.listFiles())&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>&nbsp;(subf.isFile())&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loadJarFile(subf);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #aa0d91;line-height: 26px;">else</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loadJarFile(f);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">static</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">void</span>&nbsp;<span style="color: #1c00cf;line-height: 26px;">loadJarFile</span><span style="color: #5c2699;line-height: 26px;">(File&nbsp;path)</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">throws</span>&nbsp;Exception&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URL&nbsp;url&nbsp;=&nbsp;path.toURI().toURL();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//&nbsp;可以获取到AppClassLoader,可以提到前面,不用每次都获取一次</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URLClassLoader&nbsp;classLoader&nbsp;=&nbsp;(URLClassLoader)&nbsp;ClassLoader.getSystemClassLoader();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//&nbsp;加载</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//Method&nbsp;method&nbsp;=&nbsp;URLClassLoader.class.getDeclaredMethod("sendMsg",&nbsp;Map.class);</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;method&nbsp;=&nbsp;URLClassLoader<span style="line-height: 26px;">.<span style="color: #aa0d91;line-height: 26px;">class</span>.<span style="color: #5c2699;line-height: 26px;">getMethod</span>("<span style="color: #5c2699;line-height: 26px;">sendMsg</span>",&nbsp;<span style="color: #5c2699;line-height: 26px;">Map</span>.<span style="color: #5c2699;line-height: 26px;">class</span>)</span>;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method.setAccessible(<span style="color: #aa0d91;line-height: 26px;">true</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method.invoke(classLoader,&nbsp;url);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">void</span>&nbsp;<span style="color: #1c00cf;line-height: 26px;">main</span><span style="color: #5c2699;line-height: 26px;">(String[]&nbsp;args)</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">throws</span>&nbsp;Exception</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(invokeMethod(<span style="color: #c41a16;line-height: 26px;">"hello"</span>));;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;String&nbsp;<span style="color: #1c00cf;line-height: 26px;">doExecuteMethod</span><span style="color: #5c2699;line-height: 26px;">()</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">throws</span>&nbsp;Exception</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;path&nbsp;=&nbsp;<span style="color: #c41a16;line-height: 26px;">"E:\\code-self\\bitzpp\\lib"</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;f1&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;File(path);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;result&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">null</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>&nbsp;(f1.isDirectory())&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">for</span>&nbsp;(File&nbsp;subf&nbsp;:&nbsp;f1.listFiles())&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//获取文件名称</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;name&nbsp;=&nbsp;subf.getName();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;fullPath&nbsp;=&nbsp;path&nbsp;+&nbsp;<span style="color: #c41a16;line-height: 26px;">"\\"</span>&nbsp;+&nbsp;name;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//执行反射相关的方法</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//ServiceLoaderUtils&nbsp;serviceLoaderUtils&nbsp;=&nbsp;new&nbsp;ServiceLoaderUtils();</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//result&nbsp;=&nbsp;serviceLoaderUtils.loadMethod(fullPath);</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;f&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;File(fullPath);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URL&nbsp;urlB&nbsp;=&nbsp;f.toURI().toURL();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URLClassLoader&nbsp;classLoaderA&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;URLClassLoader(<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;URL[]{urlB},&nbsp;Thread.currentThread()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getContextClassLoader());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[]&nbsp;clazz&nbsp;=&nbsp;classImpl.getClazz();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">for</span>(String&nbsp;claName&nbsp;:&nbsp;clazz){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>(name.equals(<span style="color: #c41a16;line-height: 26px;">"biz-pt-1.0-SNAPSHOT.jar"</span>)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>(!claName.equals(<span style="color: #c41a16;line-height: 26px;">"com.congge.spi.BitptImpl"</span>)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">continue</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&lt;?&gt;&nbsp;loadClass&nbsp;=&nbsp;classLoaderA.loadClass(claName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>(Objects.isNull(loadClass)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">continue</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//获取实例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;obj&nbsp;=&nbsp;loadClass.newInstance();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map&nbsp;map&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;HashMap();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//获取方法</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;method=loadClass.getDeclaredMethod(<span style="color: #c41a16;line-height: 26px;">"sendMsg"</span>,Map<span style="line-height: 26px;">.<span style="color: #aa0d91;line-height: 26px;">class</span>)</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;method.invoke(obj,map);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>(Objects.nonNull(result)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">break</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<span style="color: #aa0d91;line-height: 26px;">else</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>(name.equals(<span style="color: #c41a16;line-height: 26px;">"miz-pt-1.0-SNAPSHOT.jar"</span>)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>(!claName.equals(<span style="color: #c41a16;line-height: 26px;">"com.congge.spi.MizptImpl"</span>)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">continue</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&lt;?&gt;&nbsp;loadClass&nbsp;=&nbsp;classLoaderA.loadClass(claName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>(Objects.isNull(loadClass)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">continue</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//获取实例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;obj&nbsp;=&nbsp;loadClass.newInstance();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map&nbsp;map&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;HashMap();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//获取方法</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;method=loadClass.getDeclaredMethod(<span style="color: #c41a16;line-height: 26px;">"sendMsg"</span>,Map<span style="line-height: 26px;">.<span style="color: #aa0d91;line-height: 26px;">class</span>)</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;method.invoke(obj,map);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>(Objects.nonNull(result)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">break</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>(Objects.nonNull(result)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">break</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">return</span>&nbsp;result.toString();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;Object&nbsp;<span style="color: #1c00cf;line-height: 26px;">loadMethod</span><span style="color: #5c2699;line-height: 26px;">(String&nbsp;fullPath)</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">throws</span>&nbsp;Exception</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;f&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;File(fullPath);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URL&nbsp;urlB&nbsp;=&nbsp;f.toURI().toURL();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URLClassLoader&nbsp;classLoaderA&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;URLClassLoader(<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;URL[]{urlB},&nbsp;Thread.currentThread()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getContextClassLoader());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;result&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">null</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[]&nbsp;clazz&nbsp;=&nbsp;classImpl.getClazz();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">for</span>(String&nbsp;claName&nbsp;:&nbsp;clazz){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&lt;?&gt;&nbsp;loadClass&nbsp;=&nbsp;classLoaderA.loadClass(claName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>(Objects.isNull(loadClass)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">continue</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//获取实例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;obj&nbsp;=&nbsp;loadClass.newInstance();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map&nbsp;map&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;HashMap();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//获取方法</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;method=loadClass.getDeclaredMethod(<span style="color: #c41a16;line-height: 26px;">"sendMsg"</span>,Map<span style="line-height: 26px;">.<span style="color: #aa0d91;line-height: 26px;">class</span>)</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;method.invoke(obj,map);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">if</span>(Objects.nonNull(result)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">break</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">return</span>&nbsp;result;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">static</span>&nbsp;String&nbsp;<span style="color: #1c00cf;line-height: 26px;">invokeMethod</span><span style="color: #5c2699;line-height: 26px;">(String&nbsp;text)</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">throws</span>&nbsp;Exception</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;path&nbsp;=&nbsp;<span style="color: #c41a16;line-height: 26px;">"E:\\code-self\\bitzpp\\lib\\miz-pt-1.0-SNAPSHOT.jar"</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;f&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;File(path);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URL&nbsp;urlB&nbsp;=&nbsp;f.toURI().toURL();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URLClassLoader&nbsp;classLoaderA&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;URLClassLoader(<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;URL[]{urlB},&nbsp;Thread.currentThread()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getContextClassLoader());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&lt;?&gt;&nbsp;product&nbsp;=&nbsp;classLoaderA.loadClass(<span style="color: #c41a16;line-height: 26px;">"com.congge.spi.MizptImpl"</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//获取实例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;obj&nbsp;=&nbsp;product.newInstance();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map&nbsp;map&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;HashMap();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//获取方法</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;method=product.getDeclaredMethod(<span style="color: #c41a16;line-height: 26px;">"sendMsg"</span>,Map<span style="line-height: 26px;">.<span style="color: #aa0d91;line-height: 26px;">class</span>)</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//执行方法</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;result1&nbsp;=&nbsp;method.invoke(obj,map);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//&nbsp;TODO&nbsp;According&nbsp;to&nbsp;the&nbsp;requirements&nbsp;,&nbsp;write&nbsp;the&nbsp;implementation&nbsp;code.</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">return</span>&nbsp;result1.toString();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span

美团:这个 SQL 语句加了哪些锁?

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;overflow-wrap: break-word;text-align: left;font-size: 16px;font-family: Roboto, Oxygen, Ubuntu, Cantarell, PingFangSC-light, PingFangTC-light, &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif;"> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">美团问数据库应该是非常多的,尤其喜欢考手写 SQL 然后问你这个 SQL 语句上面加了哪些锁,你会发现其他厂面试基本很少会这样考,所以很多小伙伴遇到这种问题的时候都是一脸懵逼,这篇文章就来详细总结下 InnoDB 存储引擎中的行锁的加锁规则,并辅以实例解释。</p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">首先众所周知,InnoDB 三种行锁:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 1.8em;letter-spacing: 0.07em;"> Record Lock(记录锁):锁住某一行记录 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 1.8em;letter-spacing: 0.07em;"> Gap Lock(间隙锁):锁住一段 <span style="font-weight: 600;color: #3e4ca3;">左开右开</span>的区间 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 1.8em;letter-spacing: 0.07em;"> Next-key Lock(临键锁):锁住一段 <span style="font-weight: 600;color: #3e4ca3;">左开右闭</span>的区间 </section></li> </ul> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">哪些语句上面会加行锁?</p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">1)对于常见的 DML 语句(如 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">UPDATE</code>、<code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">DELETE</code> 和 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">INSERT</code> ),InnoDB 会自动给相应的记录行加写锁</p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">2)默认情况下对于普通 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">SELECT</code> 语句,InnoDB 不会加任何锁,但是在 Serializable 隔离级别下会加行级读锁</p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">上面两种是隐式锁定,InnoDB 也支持通过特定的语句进行显式锁定:</p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">3)<code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">SELECT * FROM table_name WHERE ... FOR UPDATE</code>,加行级写锁</p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">4)<code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE</code>,加行级读锁</p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">前置知识就不过多介绍了,在学习具体行锁加锁规则之前,小伙伴们需要记住加锁规则的两条核心:</p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">1)<span style="font-weight: 600;color: #3e4ca3;">查找过程中访问到的对象才会加锁</span></p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;border-left-color: rgba(0, 0, 0, 0.4);background: rgba(0, 0, 0, 0.05);color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;"> <p style="font-size: 16px;letter-spacing: 0.07em;color: black;line-height: 26px;">这句话该怎么理解?比如有主键 id 为 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">1 2 3 4 5 ... 10</code> 的10 条记录,我们要找到 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id = 7</code> 的记录。注意,查找并不是从第一行开始一行一行地进行遍历,而是根据 B+ 树的特性进行二分查找,所以一般存储引擎只会访问到要找的记录行(<code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id = 7</code>)的相邻区间</p> </blockquote> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">2)<span style="font-weight: 600;color: #3e4ca3;">加锁的基本单位是 Next-key Lock</span></p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">下面结合实例帮助大伙分析一条 SQL 语句上面究竟被 InnoDB 自动加上了多少个锁</p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">假设有这么一张 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">user</code> 表,<code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id</code> 为主键(唯一索引),<code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">a</code> 是普通索引(非唯一索引),<code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">b</code> 都是普通的列,其上没有任何索引:</p> <section data-tool="mdnice编辑器" style="overflow-x: auto;"> <table> <thead> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <th style="border-top-width: 1px;border-color: rgb(204, 204, 204);background-color: rgb(240, 240, 240);color: rgb(62, 76, 163);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">id (唯一索引)</th> <th style="border-top-width: 1px;border-color: rgb(204, 204, 204);background-color: rgb(240, 240, 240);color: rgb(62, 76, 163);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">a (非唯一索引)</th> <th style="border-top-width: 1px;border-color: rgb(204, 204, 204);background-color: rgb(240, 240, 240);color: rgb(62, 76, 163);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">b</th> </tr> </thead> <tbody style="border-width: 0px;border-style: initial;border-color: initial;"> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">10</td> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">4</td> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">Alice</td> </tr> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: rgb(248, 248, 248);"> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">15</td> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">8</td> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">Bob</td> </tr> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">20</td> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">16</td> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">Cilly</td> </tr> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: rgb(248, 248, 248);"> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">25</td> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">32</td> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">Druid</td> </tr> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">30</td> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">64</td> <td style="border-color: rgb(204, 204, 204);font-size: 13px;letter-spacing: 0.07em;min-width: 85px;text-align: center;">Erik</td> </tr> </tbody> </table> </section> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;letter-spacing: 0.07em;line-height: 1.8em;text-align: center;background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 70px;margin-top: 27px;margin-bottom: 27px;"><span style="display: none;"></span><span style="display: inline-block;line-height: 10px;color: rgb(62, 76, 163);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;padding-top: 29px;font-size: 20px;padding-bottom: 29px;">案例 1:唯一索引等值查询</span></h2> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">当我们用唯一索引进行等值查询的时候,根据查询的记录是否存在,加锁的规则会有所不同:</p> <ol data-tool="mdnice编辑器" style="padding-left: 25px;margin-top: 1.8em;margin-bottom: 1.8em;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 1.8em;letter-spacing: 0.07em;"> 当查询的记录是 <span style="font-weight: 600;color: #3e4ca3;">存在</span>的,Next-key Lock 会退化成 <span style="font-weight: 600;color: #3e4ca3;">记录锁</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 1.8em;letter-spacing: 0.07em;"> 当查询的记录是 <span style="font-weight: 600;color: #3e4ca3;">不存在</span>的,Next-key Lock 会退化成 <span style="font-weight: 600;color: #3e4ca3;">间隙锁</span> </section></li> </ol> <h3 data-tool="mdnice编辑器" style="letter-spacing: 0.07em;font-weight: bold;font-size: 20px;line-height: 1.4;margin-top: 27px;margin-bottom: 27px;"><span style="background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/00GYaClAoOpcG4hWQg6HhMuLOaXyFmHaQCm4DwYricicmLhHtMpBM5wvtL1pHtow63XgtD8XWuuYJGLFTVVZcho5DDWelKyBdM/640?wx_fmt=svg&quot;);background-size: 15px 15px;display: inline-block;width: 15px;height: 15px;line-height: 15px;"></span><span style="display: none;"></span><span style="font-size: 18px;display: inline-block;margin-left: 8px;color: rgb(62, 76, 163);">查询的记录存在</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">先来看个查询的记录存在的案例:</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/00GYaClAoOpcG4hWQg6HhMuLOaXyFmHaL1e8CYROaXdGwHp06hLRcpjvfW0PIANuLq8RdM0KEe7R8wYuaAHEiaYAzumwmplXf/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #c678dd;line-height: 26px;">select</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">from</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span><br><span style="color: #c678dd;line-height: 26px;">where</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">id</span>&nbsp;=&nbsp;<span style="color: #d19a66;line-height: 26px;">25</span><br><span style="color: #c678dd;line-height: 26px;">for</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">update</span>;<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">结合加锁的两条核心:查找过程中访问到的对象才会加锁 + 加锁的基本单位是 Next-key Lock(左开右闭),我们可以分析出,这条语句的加锁范围是 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(20, 25]</code></p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">不过,由于这个唯一索引等值查询的记录 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id = 25</code> 是存在的,因此,Next-key Lock 会退化成<span style="font-weight: 600;color: #3e4ca3;">记录锁</span>,因此最终的加锁范围是 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id = 25</code> 这一行</p> <h3 data-tool="mdnice编辑器" style="letter-spacing: 0.07em;font-weight: bold;font-size: 20px;line-height: 1.4;margin-top: 27px;margin-bottom: 27px;"><span style="background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/00GYaClAoOpcG4hWQg6HhMuLOaXyFmHaQCm4DwYricicmLhHtMpBM5wvtL1pHtow63XgtD8XWuuYJGLFTVVZcho5DDWelKyBdM/640?wx_fmt=svg&quot;);background-size: 15px 15px;display: inline-block;width: 15px;height: 15px;line-height: 15px;"></span><span style="display: none;"></span><span style="font-size: 18px;display: inline-block;margin-left: 8px;color: rgb(62, 76, 163);">查询的记录不存在</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">再来看查询的记录不存在的案例:</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/00GYaClAoOpcG4hWQg6HhMuLOaXyFmHaL1e8CYROaXdGwHp06hLRcpjvfW0PIANuLq8RdM0KEe7R8wYuaAHEiaYAzumwmplXf/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #c678dd;line-height: 26px;">select</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">from</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span><br><span style="color: #c678dd;line-height: 26px;">where</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">id</span>&nbsp;=&nbsp;<span style="color: #d19a66;line-height: 26px;">22</span><br><span style="color: #c678dd;line-height: 26px;">for</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">update</span>;<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">结合加锁的两条核心:查找过程中访问到的对象才会加锁 + 加锁的基本单位是 Next-key Lock(左开右闭),我们可以分析出,这条语句的加锁范围是 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(20, 25]</code></p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;border-left-color: rgba(0, 0, 0, 0.4);background: rgba(0, 0, 0, 0.05);color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;"> <p style="font-size: 16px;letter-spacing: 0.07em;color: black;line-height: 26px;">这里为什么是 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(20,25]</code> 而不是 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(20, 22]</code>,因为 id = 22 的记录不存在呀,InnoDB 先找到 id = 20 的记录,发现不匹配,于是继续往下找,发现 id = 25,因此,id = 25 的这一行被扫描到了,所以整体的加锁范围是 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(20, 25]</code></p> </blockquote> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">由于这个唯一索引等值查询的记录 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id = 22</code> 是不存在的,因此,Next-key Lock 会退化成<span style="font-weight: 600;color: #3e4ca3;">间隙锁</span>,因此最终在主键 id 上的加锁范围是 Gap Lock <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(20, 25)</code></p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;letter-spacing: 0.07em;line-height: 1.8em;text-align: center;background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 70px;margin-top: 27px;margin-bottom: 27px;"><span style="display: none;"></span><span style="display: inline-block;line-height: 10px;color: rgb(62, 76, 163);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;padding-top: 29px;font-size: 20px;padding-bottom: 29px;">案例 2:唯一索引范围查询</span></h2> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">唯一索引范围查询的规则和等值查询的规则一样,只有一个区别,就是<span style="font-weight: 600;color: #3e4ca3;">唯一索引的范围查询需要一直向右遍历到第一个不满足条件的记录</span>,下面结合案例来分析:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/00GYaClAoOpcG4hWQg6HhMuLOaXyFmHaL1e8CYROaXdGwHp06hLRcpjvfW0PIANuLq8RdM0KEe7R8wYuaAHEiaYAzumwmplXf/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #c678dd;line-height: 26px;">select</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">from</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span><br><span style="color: #c678dd;line-height: 26px;">where</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">id</span>&nbsp;&gt;=&nbsp;<span style="color: #d19a66;line-height: 26px;">20</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">and</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">id</span>&nbsp;&lt;&nbsp;<span style="color: #d19a66;line-height: 26px;">22</span><br><span style="color: #c678dd;line-height: 26px;">for</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">update</span>;<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">先来看语句查询条件的前半部分 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id &gt;= 20</code>,因此,这条语句最开始要找的第一行是 id = 20,结合加锁的两个核心,需要加上 Next-key Lock <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(15,20]</code>。又由于 id 是唯一索引,且 id = 20 的这行记录是存在的,因此会退化成<span style="font-weight: 600;color: #3e4ca3;">记录锁</span>,也就是只会对 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id = 20</code> 这一行加锁。</p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">再来看语句查询条件的后半部分 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id &lt; 22</code>,由于是范围查找,就会继续往后找第一个不满足条件的记录,也就是会找到 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id = 25</code> 这一行停下来,然后加 Next-key Lock <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(20, 25]</code>,重点来了,但<span style="font-weight: 600;color: #3e4ca3;">由于 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id = 25</code> 不满足 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id &lt; 22</code>,因此会退化成间隙锁</span>,加锁范围变为 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(20, 25)</code>。</p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">所以,上述语句在主键 id 上的最终的加锁范围是 Record Lock <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id = 20</code> 以及 &nbsp;Gap Lock <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(20, 25)</code></p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;letter-spacing: 0.07em;line-height: 1.8em;text-align: center;background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 70px;margin-top: 27px;margin-bottom: 27px;"><span style="display: none;"></span><span style="display: inline-block;line-height: 10px;color: rgb(62, 76, 163);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;padding-top: 29px;font-size: 20px;padding-bottom: 29px;">案例 3:非唯一索引等值查询</span></h2> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">当我们用非唯一索引进行等值查询的时候,根据查询的记录是否存在,加锁的规则会有所不同:</p> <ol data-tool="mdnice编辑器" style="padding-left: 25px;margin-top: 1.8em;margin-bottom: 1.8em;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 1.8em;letter-spacing: 0.07em;"> <p style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">当查询的记录是<span style="font-weight: 600;color: #3e4ca3;">存在</span>的,除了会加 Next-key Lock 外,还会额外加间隙锁(规则是向下遍历到第一个不符合条件的值才能停止),也就是会加两把锁</p> <blockquote style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;border-left-color: rgba(0, 0, 0, 0.4);background: rgba(0, 0, 0, 0.05);color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;"> <p style="font-size: 16px;letter-spacing: 0.07em;color: black;line-height: 26px;">很好记忆,就是要查找记录的左区间加 Next-key Lock,右区间加 Gap lock</p> </blockquote> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 1.8em;letter-spacing: 0.07em;"> <p style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">当查询的记录是<span style="font-weight: 600;color: #3e4ca3;">不存在</span>的,Next-key Lock 会退化成<span style="font-weight: 600;color: #3e4ca3;">间隙锁</span>(这个规则和唯一索引的等值查询是一样的)</p> </section></li> </ol> <h3 data-tool="mdnice编辑器" style="letter-spacing: 0.07em;font-weight: bold;font-size: 20px;line-height: 1.4;margin-top: 27px;margin-bottom: 27px;"><span style="background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/00GYaClAoOpcG4hWQg6HhMuLOaXyFmHaQCm4DwYricicmLhHtMpBM5wvtL1pHtow63XgtD8XWuuYJGLFTVVZcho5DDWelKyBdM/640?wx_fmt=svg&quot;);background-size: 15px 15px;display: inline-block;width: 15px;height: 15px;line-height: 15px;"></span><span style="display: none;"></span><span style="font-size: 18px;display: inline-block;margin-left: 8px;color: rgb(62, 76, 163);">查询的记录存在</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">先来看个查询的记录存在的案例:</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/00GYaClAoOpcG4hWQg6HhMuLOaXyFmHaL1e8CYROaXdGwHp06hLRcpjvfW0PIANuLq8RdM0KEe7R8wYuaAHEiaYAzumwmplXf/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #c678dd;line-height: 26px;">select</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">from</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span><br><span style="color: #c678dd;line-height: 26px;">where</span>&nbsp;a&nbsp;=&nbsp;<span style="color: #d19a66;line-height: 26px;">16</span><br><span style="color: #c678dd;line-height: 26px;">for</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">update</span>;<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">结合加锁的两条核心,这条语句首先会对普通索引 a 加上 Next-key Lock,范围是 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(8,16]</code></p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">又因为是非唯一索引等值查询,且查询的记录 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;"> a= 16</code> 是存在的,所以还会加上间隙锁,规则是向下遍历到第一个不符合条件的值才能停止,因此间隙锁的范围是 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(16,32)</code></p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">所以,上述语句在普通索引 a 上的最终加锁范围是 Next-key Lock <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(8,16]</code> 以及 &nbsp;Gap Lock <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(16,32)</code></p> <h3 data-tool="mdnice编辑器" style="letter-spacing: 0.07em;font-weight: bold;font-size: 20px;line-height: 1.4;margin-top: 27px;margin-bottom: 27px;"><span style="background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/00GYaClAoOpcG4hWQg6HhMuLOaXyFmHaQCm4DwYricicmLhHtMpBM5wvtL1pHtow63XgtD8XWuuYJGLFTVVZcho5DDWelKyBdM/640?wx_fmt=svg&quot;);background-size: 15px 15px;display: inline-block;width: 15px;height: 15px;line-height: 15px;"></span><span style="display: none;"></span><span style="font-size: 18px;display: inline-block;margin-left: 8px;color: rgb(62, 76, 163);">查询的记录不存在</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">再来看查询的记录不存在的案例:</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/00GYaClAoOpcG4hWQg6HhMuLOaXyFmHaL1e8CYROaXdGwHp06hLRcpjvfW0PIANuLq8RdM0KEe7R8wYuaAHEiaYAzumwmplXf/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #c678dd;line-height: 26px;">select</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">from</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span><br><span style="color: #c678dd;line-height: 26px;">where</span>&nbsp;a&nbsp;=&nbsp;<span style="color: #d19a66;line-height: 26px;">18</span><br><span style="color: #c678dd;line-height: 26px;">for</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">update</span>;<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">结合加锁的两条核心,这条语句首先会对普通索引 a 加上 Next-key Lock,范围是 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(16,32]</code></p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">但是由于查询的记录 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">a = 18</code> 是不存在的,因此 Next-key Lock 会退化为间隙锁,即最终在普通索引 a 上的加锁范围是 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(16,32)</code>。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;letter-spacing: 0.07em;line-height: 1.8em;text-align: center;background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 70px;margin-top: 27px;margin-bottom: 27px;"><span style="display: none;"></span><span style="display: inline-block;line-height: 10px;color: rgb(62, 76, 163);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;padding-top: 29px;font-size: 20px;padding-bottom: 29px;">案例 4:非唯一索引范围查询</span></h2> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">范围查询和等值查询的区别在上面唯一索引章节已经介绍过了,就是范围查询需要一直向右遍历到第一个不满足条件的记录,和唯一索引范围查询不同的是,<span style="font-weight: 600;color: #3e4ca3;">非唯一索引的范围查询并不会退化成 Record Lock 或者 Gap Lock</span>。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/00GYaClAoOpcG4hWQg6HhMuLOaXyFmHaL1e8CYROaXdGwHp06hLRcpjvfW0PIANuLq8RdM0KEe7R8wYuaAHEiaYAzumwmplXf/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #c678dd;line-height: 26px;">select</span>&nbsp;*&nbsp;<span style="color: #c678dd;line-height: 26px;">from</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">user</span><br><span style="color: #c678dd;line-height: 26px;">where</span>&nbsp;a&nbsp;&gt;=&nbsp;<span style="color: #d19a66;line-height: 26px;">16</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">and</span>&nbsp;a&nbsp;&lt;&nbsp;<span style="color: #d19a66;line-height: 26px;">18</span><br><span style="color: #c678dd;line-height: 26px;">for</span>&nbsp;<span style="color: #c678dd;line-height: 26px;">update</span>;<br></code></pre> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">先来看语句查询条件的前半部分 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">a &gt;= 16</code>,因此,这条语句最开始要找的第一行是 a = 16,结合加锁的两个核心,需要加上 Next-key Lock <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(8,16]</code>。虽然非唯一索引 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">a = 16</code> 的这行记录是存在的,但此时<span style="font-weight: 600;color: #3e4ca3;">并不会</span>像唯一索引那样退化成记录锁。</p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">再来看语句查询条件的后半部分 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">a &lt; 18</code>,由于是范围查找,就会继续往后找第一个不满足条件的记录,也就是会找到 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id = 32</code> 这一行停下来,然后加 Next-key Lock <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(16, 32]</code>。虽然 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id = 32</code> 不满足 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">id &lt; 18</code>,但此时<span style="font-weight: 600;color: #3e4ca3;">并不会</span>向唯一索引那样退化成间隙锁。</p> <p data-tool="mdnice编辑器" style="margin-top: 1.8em;margin-bottom: 1.8em;line-height: 1.8em;letter-spacing: 0.07em;">所以,上述语句在普通索引 a 上的最终的加锁范围是 Next-key Lock <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(8, 16]</code> 和 &nbsp;<code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(16, 32]</code>,也就是 <code style="overflow-wrap: break-word;border-radius: 4px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;letter-spacing: 0.07em;font-size: 13px;color: rgb(155, 110, 35);background-color: rgb(255, 249, 227);padding: 3px;">(8, 32]</code>。</p> </section>

SpringBoot 集成 Camunda 流程引擎,实现一套完整的业务流程

作者:微信小助手

<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, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;" data-mpa-powered-by="yiban.io"> <h1 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 1.8em;color: rgb(0, 150, 136);margin: 1.2em auto;text-align: center;border-bottom: 1px solid rgb(0, 150, 136);"><span style="display: none;"></span>前言</h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">项目中需要用到工作流引擎来设计部分业务流程,框架选型最终选择了 Camunda7,关于 Camunda以及 Activity 等其他工作流 引擎的介绍及对比不再介绍,这里只介绍与现有Springboot项目的集成以及具体使用及配置</p> <h1 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 1.8em;color: rgb(0, 150, 136);margin: 1.2em auto;text-align: center;border-bottom: 1px solid rgb(0, 150, 136);"><span style="display: none;"></span>概念</h1> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><strong>流程(PROCESS)</strong>: 通过工具建模最终生成的BPMN文件,里面有整个流程的定义</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><strong>流程实例(Instance)</strong>:流程启动后的实例</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><strong>流程变量(Variables)</strong>:流程任务之间传递的参数</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><strong>任务(TASK)</strong>:流程中定义的每一个节点</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><strong>流程部署</strong>:将之前流程定义的.bpmn文件部署到工作流平台</p> </section></li> </ul> <h1 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 1.8em;color: rgb(0, 150, 136);margin: 1.2em auto;text-align: center;border-bottom: 1px solid rgb(0, 150, 136);"><span style="display: none;"></span>核心组件</h1> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><strong>Process Engine</strong>-流程引擎</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><strong>Web Applicatons</strong>- 基于web的管理页面</p> </section></li> </ul> <h1 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 1.8em;color: rgb(0, 150, 136);margin: 1.2em auto;text-align: center;border-bottom: 1px solid rgb(0, 150, 136);"><span style="display: none;"></span>API介绍</h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">官方文档</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-bottom: none;font-size: 0.9em;overflow: auto;background: rgba(0, 0, 0, 0.05);padding: 10px 10px 10px 1em;margin-bottom: 20px;margin-top: 20px;border-left-width: 2px;border-left-color: rgb(136, 136, 136);border-right: 2px solid rgb(136, 136, 136);color: rgb(119, 119, 119);"> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> https://docs.camunda.org/manual/7.18/user-guide/process-engine/process-engine-api/ </section></li> </ul> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">下面是官网的一些文档,有时间可以看看,下面说一些核心的东西。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.7723342939481268" src="/upload/d578cb796c08da575153f305da5385c4.png" data-type="png" data-w="1041" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;margin: 0.6em auto;padding-left: 10px;border-left: 2px solid rgb(0, 150, 136);"><span style="display: none;"></span>ProcessEngine<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">为流程引擎,可以通过他获取相关service,里面集成了很多相关service,默认实现如下:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.7103896103896103" src="/upload/6943088d28ab1346e9724b048113cbc5.png" data-type="png" data-w="770" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;margin: 0.6em auto;padding-left: 10px;border-left: 2px solid rgb(0, 150, 136);"><span style="display: none;"></span>RepositoryService<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">此服务提供用于管理和操作部署和流程定义的操作,使用camunda的第一要务</p> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;margin: 0.6em auto;padding-left: 10px;border-left: 2px solid rgb(0, 150, 136);"><span style="display: none;"></span>RuntimeService<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">运行相关,启动流程实例、删除、搜索等</p> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;margin: 0.6em auto;padding-left: 10px;border-left: 2px solid rgb(0, 150, 136);"><span style="display: none;"></span>TaskService<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">所有围绕任务相关的操作,如完成、分发、认领等</p> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;margin: 0.6em auto;padding-left: 10px;border-left: 2px solid rgb(0, 150, 136);"><span style="display: none;"></span>HistoryService<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">提供引擎搜集的历史数据服务</p> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;margin: 0.6em auto;padding-left: 10px;border-left: 2px solid rgb(0, 150, 136);"><span style="display: none;"></span>IdentityService<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">用户相关,实际中用不太到</p> <h1 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 1.8em;color: rgb(0, 150, 136);margin: 1.2em auto;text-align: center;border-bottom: 1px solid rgb(0, 150, 136);"><span style="display: none;"></span>Springboot集成</h1> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;margin: 0.6em auto;padding-left: 10px;border-left: 2px solid rgb(0, 150, 136);"><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;text-align: justify;"><strong>maven</strong></p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-bottom: none;font-size: 0.9em;overflow: auto;background: rgba(0, 0, 0, 0.05);padding: 10px 10px 10px 1em;margin-bottom: 20px;margin-top: 20px;border-left-width: 2px;border-left-color: rgb(136, 136, 136);border-right: 2px solid rgb(136, 136, 136);color: rgb(119, 119, 119);"> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> https://mvnrepository.com/search?q=org.camunda.bpm.springboot </section></li> </ul> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">可以根据需要引用版本,我这边用的是 7.18</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">需要3个maven依赖,分别是对应 流程引擎、Web管理平台、提供rest api操作接口包</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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wJibWkqN1bUMGV1UTPd8FdvfkC76zoMv0aYPZGDVibVmqsjAVtgd9evwcySjKot950ia5VMZcFxSINTIttP6s2FwE56z3bOjxMJ/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span>org.camunda.bpm.springboot<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span>camunda-bpm-spring-boot-starter<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span>7.18.0<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span><br><span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br><span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span>org.camunda.bpm.springboot<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span>camunda-bpm-spring-boot-starter-rest<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span>7.18.0<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span><br><span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br><span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span>org.camunda.bpm.springboot<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span>camunda-bpm-spring-boot-starter-webapp<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span>7.18.0<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span><br><span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;"><strong>数据库</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">我这边使用的是mysql,建了个新库 camunda(可自定义),启动后会自动生成所需表结构</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;"><strong>POM文件</strong></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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wJibWkqN1bUMGV1UTPd8FdvfkC76zoMv0aYPZGDVibVmqsjAVtgd9evwcySjKot950ia5VMZcFxSINTIttP6s2FwE56z3bOjxMJ/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #61aeee;line-height: 26px;">&lt;?xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"?&gt;</span><br><span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">project</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">xmlns</span>=<span style="color: #98c379;line-height: 26px;">"http://maven.apache.org/POM/4.0.0"</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">xmlns:xsi</span>=<span style="color: #98c379;line-height: 26px;">"http://www.w3.org/2001/XMLSchema-instance"</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">xsi:schemaLocation</span>=<span style="color: #98c379;line-height: 26px;">"http://maven.apache.org/POM/4.0.0&nbsp;https://maven.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">modelVersion</span>&gt;</span>4.0.0<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">modelVersion</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">parent</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span>org.springframework.boot<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span>spring-boot-starter-parent<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span>2.7.3<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">relativePath</span>/&gt;</span>&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">&lt;!--&nbsp;lookup&nbsp;parent&nbsp;from&nbsp;repository&nbsp;--&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">parent</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span>com.example<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span>camunda-demo<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span>0.0.1-SNAPSHOT<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">name</span>&gt;</span>camunda-demo<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">name</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">description</span>&gt;</span>camunda-demo<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">description</span>&gt;</span><br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">properties</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">java.version</span>&gt;</span>17<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">java.version</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">properties</span>&gt;</span><br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">dependencies</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span>org.springframework.boot<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span>spring-boot-starter<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span>org.camunda.bpm.springboot<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span>camunda-bpm-spring-boot-starter<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span>7.18.0<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span>org.camunda.bpm.springboot<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span>camunda-bpm-spring-boot-starter-rest<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span>7.18.0<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span>org.camunda.bpm.springboot<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span>camunda-bpm-spring-boot-starter-webapp<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span>7.18.0<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span>mysql<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span>mysql-connector-java<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span>8.0.32<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">version</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span>org.springframework.boot<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span>spring-boot-starter-test<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">scope</span>&gt;</span>test<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">scope</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">dependency</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">dependencies</span>&gt;</span><br>&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">build</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">plugins</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">plugin</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span>org.springframework.boot<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">groupId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span>spring-boot-maven-plugin<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">artifactId</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">plugin</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">plugins</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">build</span>&gt;</span><br>&nbsp;<br><span style="line-height: 26px;">&lt;/<span style="color: #e06c75;line-height: 26px;">project</span>&gt;</span><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;"><strong>application.yml</strong></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(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wJibWkqN1bUMGV1UTPd8FdvfkC76zoMv0aYPZGDVibVmqsjAVtgd9evwcySjKot950ia5VMZcFxSINTIttP6s2FwE56z3bOjxMJ/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #d19a66;line-height: 26px;">server:</span><br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">port:</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">8081</span><br>&nbsp;<br>&nbsp;<br><span style="color: #5c6370;font-style: italic;line-height: 26px;">#&nbsp;camunda登录信息配置</span><br><span style="color: #d19a66;line-height: 26px;">camunda.bpm:</span><br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">admin-user:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">id:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">admin</span>&nbsp;&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">#用户名</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">password:</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">123456</span>&nbsp;&nbsp;<span style="color: #5c6370;font-style: italic;line-height: 26px;">#密码</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">firstName:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">yu</span><br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">filter:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">create:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">All</span>&nbsp;<span style="color: #98c379;line-height: 26px;">tasks</span><br>&nbsp;<br><span style="color: #5c6370;font-style: italic;line-height: 26px;">#&nbsp;mysql连接信息</span><br><span style="color: #d19a66;line-height: 26px;">spring:</span><br>&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">datasource:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">driver-class-name:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">com.mysql.cj.jdbc.Driver</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">url:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">jdbc:mysql://localhost:8101/camunda</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">username:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">root</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">password:</span>&nbsp;<span style="color: #d19a66;line-height: 26px;">123456</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #d19a66;line-height: 26px;">type:</span>&nbsp;<span style="color: #98c379;line-height: 26px;">com.mysql.cj.jdbc.MysqlDataSource</span><br></code></pre> <h3 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 20px;margin: 0.6em auto;padding-left: 10px;border-left: 2px solid rgb(0, 150, 136);"><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;text-align: justify;">准备好前置工作,启动后效果如下:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.34814814814814815" src="/upload/e013f9d939a41e8f720a953efa8fcfb5.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;"><strong>数据库表结构</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">启动后自动生成的表结构如下</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.46111111111111114" src="/upload/30a54325c43b7728c4f9b7b77485df00.png" data-type="png" data-w="1080" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">大概有这么几个表模块,重要的详细介绍下:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="color: black;">ACT_ID_</strong> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">这部分表示用户模块,配置文件里面的用户,信息就在此模块</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.31784386617100374" src="/upload/4d03a33e5da7d8a5c3bb325330036129.png" data-type="png" data-w="1076" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="color: black;">ACT_HI_</strong> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">表示流程历史记录</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><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: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(0, 150, 136);">act_hi_actinst</code>: 执行的活动历史</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><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: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(0, 150, 136);">act_hi_taskinst</code>:执行任务历史</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><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: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(0, 150, 136);">act_hi_procinst</code>:执行流程实例历史</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><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: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(0, 150, 136);">act_hi_varinst</code>:流程变量历史表</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><strong>ACT_RE_</strong></p> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">表示流程资源存储</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><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: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(0, 150, 136);">act_re_procdef</code>:流程定义存储</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><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: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(0, 150, 136);">act_re_deployment</code>: 自动部署,springboot每次启动都会重新部署,生成记录</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><strong>ACT_RU_</strong></p> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">表示流程运行时表数据,流程结束后会删除</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><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: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(0, 150, 136);">act_ru_execution</code>:运行时流程实例</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><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: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(0, 150, 136);">act_ru_task</code>:运行时的任务</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><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: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(0, 150, 136);">act_ru_variable</code>:运行时的流程变量</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: black;text-align: justify;"><strong>ACT_GE_</strong></p> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">流程通用数据</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <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: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(0, 150, 136);">act_ge_bytearray</code>:每次部署的文件2进制数据,所以如果文件修改后,重启也没用,因为重新生成了记录,需要清掉数据库,或者这个表记录 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;"><strong>登录界面</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;text-align: justify;">登录地址为 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgb

SpringBoot 插件化开发模式,强烈推荐!

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" data-mpa-powered-by="yiban.io" style="padding-right: 10px;padding-left: 10px;outline: 0px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;"> <h1 data-tool="mdnice编辑器" style="margin: 1.2em auto;outline: 0px;font-weight: bold;font-size: 1.8em;color: rgb(0, 150, 136);text-align: center;border-bottom: 1px solid rgb(0, 150, 136);">一、前言</h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">插件化开发模式正在很多编程语言或技术框架中得以广泛的应用实践,比如大家熟悉的jenkins,docker可视化管理平台rancher,以及日常编码使用的编辑器idea,vscode等,随处可见的带有热插拔功能的插件,让系统像插了翅膀一样,大大提升了系统的扩展性和伸缩性,也拓展了系统整体的使用价值,那么为什么要使用插件呢?</p> <h3 data-tool="mdnice编辑器" style="margin: 0.6em auto;padding-left: 10px;outline: 0px;font-weight: bold;font-size: 20px;border-left: 2px solid rgb(0, 150, 136);">1.1 使用插件的好处</h3> <h4 data-tool="mdnice编辑器" style="margin: 0.6em auto;padding-left: 10px;outline: 0px;font-weight: bold;font-size: 1.2em;border-left: 2px dashed rgb(0, 150, 136);">1.1.1 模块解耦</h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">实现服务模块之间解耦的方式有很多,但是插件来说,其解耦的程度似乎更高,而且更灵活,可定制化、个性化更好。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">举例来说,代码中可以使用设计模式来选择使用哪种方式发送短信给下单完成的客户,问题是各个短信服务商并不一定能保证在任何情况下都能发送成功,怎么办呢?这时候设计模式也没法帮你解决这个问题,如果使用定制化插件的方式,结合外部配置参数,假设系统中某种短信发送不出去了,这时候就可以利用插件动态植入,切换为不同的厂商发短信了。</p> <h4 data-tool="mdnice编辑器" style="margin: 0.6em auto;padding-left: 10px;outline: 0px;font-weight: bold;font-size: 1.2em;border-left: 2px dashed rgb(0, 150, 136);">1.1.2 提升扩展性和开放性</h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">以spring来说,之所以具备如此广泛的生态,与其自身内置的各种可扩展的插件机制是分不开的,试想为什么使用了spring框架之后可以很方便的对接其他中间件,那就是spring框架提供了很多基于插件化的扩展点。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">插件化机制让系统的扩展性得以提升,从而可以丰富系统的周边应用生态。</p> <h4 data-tool="mdnice编辑器" style="margin: 0.6em auto;padding-left: 10px;outline: 0px;font-weight: bold;font-size: 1.2em;border-left: 2px dashed rgb(0, 150, 136);">1.1.3 方便第三方接入</h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">有了插件之后,第三方应用或系统如果要对接自身的系统,直接基于系统预留的插件接口完成一套适合自己业务的实现即可,而且对自身系统的侵入性很小,甚至可以实现基于配置参数的热加载,方便灵活,开箱即用。</p> <h3 data-tool="mdnice编辑器" style="margin: 0.6em auto;padding-left: 10px;outline: 0px;font-weight: bold;font-size: 20px;border-left: 2px solid rgb(0, 150, 136);">1.2 插件化常用实现思路</h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">以java为例,这里结合实际经验,整理一些常用的插件化实现思路:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;"> <li style="outline: 0px;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);"> spi机制; </section></li> <li style="outline: 0px;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);"> 约定配置和目录,利用反射配合实现; </section></li> <li style="outline: 0px;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);"> springboot中的Factories机制; </section></li> <li style="outline: 0px;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);"> java agent(探针)技术; </section></li> <li style="outline: 0px;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);"> spring内置扩展点; </section></li> <li style="outline: 0px;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);"> 第三方插件包,例如:spring-plugin-core; </section></li> <li style="outline: 0px;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);"> spring aop技术; </section></li> </ul> <h1 data-tool="mdnice编辑器" style="margin: 1.2em auto;outline: 0px;font-weight: bold;font-size: 1.8em;color: rgb(0, 150, 136);text-align: center;border-bottom: 1px solid rgb(0, 150, 136);">二、Java常用插件实现方案</h1> <h3 data-tool="mdnice编辑器" style="margin: 0.6em auto;padding-left: 10px;outline: 0px;font-weight: bold;font-size: 20px;border-left: 2px solid rgb(0, 150, 136);">2.1 serviceloader方式</h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">serviceloader是java提供的spi模式的实现。按照接口开发实现类,而后配置,java通过ServiceLoader来实现统一接口不同实现的依次调用。而java中最经典的serviceloader的使用就是Java的spi机制。</p> <h4 data-tool="mdnice编辑器" style="margin: 0.6em auto;padding-left: 10px;outline: 0px;font-weight: bold;font-size: 1.2em;border-left: 2px dashed rgb(0, 150, 136);">2.1.1 java spi</h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">SPI全称 Service Provider Interface ,是JDK内置的一种服务发现机制,SPI是一种动态替换扩展机制,比如有个接口,你想在运行时动态给他添加实现,你只需按照规范给他添加一个实现类即可。比如大家熟悉的jdbc中的Driver接口,不同的厂商可以提供不同的实现,有mysql的,也有oracle的,而Java的SPI机制就可以为某个接口寻找服务的实现。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">下面用一张简图说明下SPI机制的原理</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img js_img_placeholder wx_img_placeholder" data-ratio="0.3431603773584906" src="/upload/4bc4a1f3904002f4167b0db1a17dbe9c.png" data-type="png" data-w="848" style="margin-right: auto;margin-left: auto;outline: 0px;border-radius: 8px;display: block;background-size: 16px !important;height: 225.456px !important;width: 657px !important;"> </figure> <h4 data-tool="mdnice编辑器" style="margin: 0.6em auto;padding-left: 10px;outline: 0px;font-weight: bold;font-size: 1.2em;border-left: 2px dashed rgb(0, 150, 136);">2.1.2 java spi 简单案例</h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">如下工程目录,在某个应用工程中定义一个插件接口,而其他应用工程为了实现这个接口,只需要引入当前工程的jar包依赖进行实现即可,这里为了演示我就将不同的实现直接放在同一个工程下;</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img js_img_placeholder wx_img_placeholder" data-ratio="0.9521178637200737" src="/upload/d3fd2956b19d1104d73d74b56dde435e.png" data-type="png" data-w="543" style="margin-right: auto;margin-left: auto;outline: 0px;border-radius: 8px;display: block;background-size: 16px !important;height: 517px !important;width: 543px !important;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">定义接口</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wJibWkqN1bUMGV1UTPd8Fdr35s4TRGO0vFVEMBmVeVgLFLytedYBQIxWw4V9puicSoUdS9eRvPNOLicFHv898qoFUKiaeuxLdUln/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;"><span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">public</span>&nbsp;<span style="outline: 0px;line-height: 26px;"><span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">interface</span>&nbsp;<span style="outline: 0px;color: rgb(230, 192, 123);line-height: 26px;">MessagePlugin</span>&nbsp;</span>{<br style="outline: 0px;">&nbsp;<br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;line-height: 26px;"><span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">public</span>&nbsp;String&nbsp;<span style="outline: 0px;color: rgb(97, 174, 238);line-height: 26px;">sendMsg</span><span style="outline: 0px;line-height: 26px;">(Map&nbsp;msgMap)</span></span>;<br style="outline: 0px;">&nbsp;<br style="outline: 0px;">}<br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">定义两个不同的实现</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wJibWkqN1bUMGV1UTPd8Fdr35s4TRGO0vFVEMBmVeVgLFLytedYBQIxWw4V9puicSoUdS9eRvPNOLicFHv898qoFUKiaeuxLdUln/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;"><span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">public</span>&nbsp;<span style="outline: 0px;line-height: 26px;"><span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">class</span>&nbsp;<span style="outline: 0px;color: rgb(230, 192, 123);line-height: 26px;">AliyunMsg</span>&nbsp;<span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">implements</span>&nbsp;<span style="outline: 0px;color: rgb(230, 192, 123);line-height: 26px;">MessagePlugin</span>&nbsp;</span>{<br style="outline: 0px;">&nbsp;<br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;color: rgb(97, 174, 238);line-height: 26px;">@Override</span><br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;line-height: 26px;"><span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">public</span>&nbsp;String&nbsp;<span style="outline: 0px;color: rgb(97, 174, 238);line-height: 26px;">sendMsg</span><span style="outline: 0px;line-height: 26px;">(Map&nbsp;msgMap)</span>&nbsp;</span>{<br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span style="outline: 0px;color: rgb(152, 195, 121);line-height: 26px;">"aliyun&nbsp;sendMsg"</span>);<br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">return</span>&nbsp;<span style="outline: 0px;color: rgb(152, 195, 121);line-height: 26px;">"aliyun&nbsp;sendMsg"</span>;<br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;}<br style="outline: 0px;">}<br style="outline: 0px;"></code></pre> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;outline: 0px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wJibWkqN1bUMGV1UTPd8Fdr35s4TRGO0vFVEMBmVeVgLFLytedYBQIxWw4V9puicSoUdS9eRvPNOLicFHv898qoFUKiaeuxLdUln/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 657px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;"><span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">public</span>&nbsp;<span style="outline: 0px;line-height: 26px;"><span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">class</span>&nbsp;<span style="outline: 0px;color: rgb(230, 192, 123);line-height: 26px;">TencentMsg</span>&nbsp;<span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">implements</span>&nbsp;<span style="outline: 0px;color: rgb(230, 192, 123);line-height: 26px;">MessagePlugin</span>&nbsp;</span>{<br style="outline: 0px;">&nbsp;<br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;color: rgb(97, 174, 238);line-height: 26px;">@Override</span><br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;line-height: 26px;"><span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">public</span>&nbsp;String&nbsp;<span style="outline: 0px;color: rgb(97, 174, 238);line-height: 26px;">sendMsg</span><span style="outline: 0px;line-height: 26px;">(Map&nbsp;msgMap)</span>&nbsp;</span>{<br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span style="outline: 0px;color: rgb(152, 195, 121);line-height: 26px;">"tencent&nbsp;sendMsg"</span>);<br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">return</span>&nbsp;<span style="outline: 0px;color: rgb(152, 195, 121);line-height: 26px;">"tencent&nbsp;sendMsg"</span>;<br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;}<br style="outline: 0px;">}<br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;">在resources目录按照规范要求创建文件目录,并填写实现类的全类名</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.25462962962962965" src="/upload/b07387ea7f4bc401fe1484916ad23e8f.png" data-type="png" data-w="1080" style="margin-right: auto;margin-left: auto;outline: 0px;display: block;width: 677px !important;visibility: visible !important;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;text-align: justify;"><strong s

Nginx一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、防盗链、SSL、性能优化...

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding-right: 10px;padding-left: 10px;outline: 0px;text-wrap: wrap;background-color: rgb(255, 255, 255);font-size: 16px;color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;visibility: visible;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);visibility: visible;"><strong>干货!文章有点长,建议先收藏</strong></p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;visibility: visible;"> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 引言 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 一、性能怪兽-Nginx概念深入浅出 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 二、Nginx环境搭建 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 三、Nginx反向代理-负载均衡 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 四、Nginx动静分离 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 五、Nginx资源压缩 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 六、Nginx缓冲区 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 七、Nginx缓存机制 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 八、Nginx实现IP黑白名单 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 九、Nginx跨域配置 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 十、Nginx防盗链设计 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 十一、Nginx大文件传输配置 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 十二、Nginx配置SLL证书 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 十三、Nginx的高可用 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 十四、Nginx性能优化 </section></li> <li style="outline: 0px;visibility: visible;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);visibility: visible;"> 十五、放在最后的结尾 </section></li> </ul> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 30px;outline: 0px;font-weight: bold;font-size: 22px;border-bottom: 2px solid rgb(89, 89, 89);color: rgb(89, 89, 89);"><span style="outline: 0px;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);">引言</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">早期的业务都是基于单体节点部署,由于前期访问流量不大,因此单体结构也可满足需求,但随着业务增长,流量也越来越大,那么最终单台服务器受到的访问压力也会逐步增高。时间一长,单台服务器性能无法跟上业务增长,就会造成线上频繁宕机的现象发生,最终导致系统瘫痪无法继续处理用户的请求。</p> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding-top: 10px;padding-right: 10px;padding-bottom: 10px;outline: 0px;border-width: initial;border-style: none;border-color: initial;color: rgb(136, 136, 136);font-size: 0.9em;overflow: auto;background: rgba(0, 0, 0, 0.05);line-height: 1.8;"> <span style="outline: 0px;color: rgb(85, 85, 85);font-size: 4em;font-family: Arial, serif;line-height: 1em;font-weight: 700;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;outline: 0px;font-size: 16px;color: black;line-height: 26px;display: inline;">从上面的描述中,主要存在两个问题:①单体结构的部署方式无法承载日益增长的业务流量。②当后端节点宕机后,整个系统会陷入瘫痪,导致整个项目不可用。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">因此在这种背景下,引入负载均衡技术可带来的收益:</p> <ul data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;outline: 0px;"> <li style="outline: 0px;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="outline: 0px;color: rgb(71, 193, 168);">「系统的高可用:」</strong>&nbsp;当某个节点宕机后可以迅速将流量转移至其他节点。 </section></li> <li style="outline: 0px;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="outline: 0px;color: rgb(71, 193, 168);">「系统的高性能:」</strong>&nbsp;多台服务器共同对外提供服务,为整个系统提供了更高规模的吞吐。 </section></li> <li style="outline: 0px;"> <section style="margin-top: 5px;margin-bottom: 5px;outline: 0px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="outline: 0px;color: rgb(71, 193, 168);">「系统的拓展性:」</strong>&nbsp;当业务再次出现增长或萎靡时,可再加入/减少节点,灵活伸缩。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">OK~,既然引入负载均衡技术可给我们带来如此巨大的好处,那么又有那些方案可供选择呢?主要有两种负载方案,<strong style="outline: 0px;color: rgb(71, 193, 168);">「「硬件层面与软件层面」」</strong>&nbsp;,比较常用的硬件负载器有<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">A10、F5</code>等,但这些机器动辄大几万乃至几十万的成本,因此一般大型企业会采用该方案,如银行、国企、央企等。而成本有限,但依旧想做负载均衡的项目,那么可在软件层面实现,如典型的<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>等,软件层的负载也是本文的重点,毕竟<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Boss</code>们的准则之一就是:<strong style="outline: 0px;color: rgb(71, 193, 168);">「「能靠技术实现的就尽量不花钱。」」</strong></p> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding-top: 10px;padding-right: 10px;padding-bottom: 10px;outline: 0px;border-width: initial;border-style: none;border-color: initial;color: rgb(136, 136, 136);font-size: 0.9em;overflow: auto;background: rgba(0, 0, 0, 0.05);line-height: 1.8;"> <span style="outline: 0px;color: rgb(85, 85, 85);font-size: 4em;font-family: Arial, serif;line-height: 1em;font-weight: 700;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;outline: 0px;font-size: 16px;color: black;line-height: 26px;display: inline;">当然,如果你认为本文对你而言有帮助,记得点赞、收藏、关注三连噢!</p> </blockquote> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 30px;outline: 0px;font-weight: bold;font-size: 22px;border-bottom: 2px solid rgb(89, 89, 89);color: rgb(89, 89, 89);"><span style="outline: 0px;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);">一、性能怪兽-Nginx概念深入浅出</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>是目前负载均衡技术中的主流方案,几乎绝大部分项目都会使用它,<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>是一个轻量级的高性能<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">HTTP</code>反向代理服务器,同时它也是一个通用类型的代理服务器,支持绝大部分协议,如<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">TCP、UDP、SMTP、HTTPS</code>等。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.396875" src="/upload/44a2091ca8f680853fa0f6042e5d25f0.jpg" data-w="640" style="margin-right: auto;margin-left: auto;outline: 0px;display: block;visibility: visible !important;width: 640px !important;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>与Redis相同,都是基于多路复用模型构建出的产物,因此它与<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Redis</code>同样具备&nbsp;<strong style="outline: 0px;color: rgb(71, 193, 168);">「「资源占用少、并发支持高」」</strong>&nbsp;的特点,在理论上单节点的<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>同时支持<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">5W</code>并发连接,而实际生产环境中,硬件基础到位再结合简单调优后确实能达到该数值。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">先来看看<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>引入前后,客户端请求处理流程的对比:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.5796875" src="/upload/85f0aa7a7c0d80a86c7a98c200ea5124.jpg" data-w="640" style="margin-right: auto;margin-left: auto;outline: 0px;border-radius: 8px;display: block;background-size: 16px !important;width: 640px !important;visibility: visible !important;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">原本客户端是直接请求目标服务器,由目标服务器直接完成请求处理工作,但加入<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>后,所有的请求会先经过<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>,再由其进行分发到具体的服务器处理,处理完成后再返回<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>,最后由<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>将最终的响应结果返回给客户端。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">了解了<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>的基本概念后,再来快速搭建一下环境,以及了解一些<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>的高级特性,如动静分离、资源压缩、缓存配置、<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">IP</code>黑名单、高可用保障等。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 30px;outline: 0px;font-weight: bold;font-size: 22px;border-bottom: 2px solid rgb(89, 89, 89);color: rgb(89, 89, 89);"><strong><span style="outline: 0px;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);">二、Nginx环境搭建</span></strong></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">❶首先创建<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>的目录并进入:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;mkdir&nbsp;/soft&nbsp;&amp;&amp;&nbsp;mkdir&nbsp;/soft/nginx/&nbsp;&nbsp;</span><br style="outline: 0px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;cd&nbsp;/soft/nginx/&nbsp;&nbsp;</span><br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">❷下载<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>的安装包,可以通过<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">FTP</code>工具上传离线环境包,也可通过<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">wget</code>命令在线获取安装包:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;wget&nbsp;https://nginx.org/download/nginx-1.21.6.tar.gz&nbsp;&nbsp;</span><br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">没有<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">wget</code>命令的可通过<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">yum</code>命令安装:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;yum&nbsp;-y&nbsp;install&nbsp;wget&nbsp;&nbsp;</span><br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">❸解压<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>的压缩包:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;tar&nbsp;-xvzf&nbsp;nginx-1.21.6.tar.gz&nbsp;&nbsp;</span><br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">❹下载并安装<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>所需的依赖库和包:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;yum&nbsp;install&nbsp;--downloadonly&nbsp;--downloaddir=/soft/nginx/&nbsp;gcc-c++&nbsp;&nbsp;</span><br style="outline: 0px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;yum&nbsp;install&nbsp;--downloadonly&nbsp;--downloaddir=/soft/nginx/&nbsp;pcre&nbsp;pcre-devel4&nbsp;&nbsp;</span><br style="outline: 0px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;yum&nbsp;install&nbsp;--downloadonly&nbsp;--downloaddir=/soft/nginx/&nbsp;zlib&nbsp;zlib-devel&nbsp;&nbsp;</span><br style="outline: 0px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;yum&nbsp;install&nbsp;--downloadonly&nbsp;--downloaddir=/soft/nginx/&nbsp;openssl&nbsp;openssl-devel&nbsp;</span><br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">也可以通过<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">yum</code>命令一键下载(推荐上面哪种方式):</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;yum&nbsp;-y&nbsp;install&nbsp;gcc&nbsp;zlib&nbsp;zlib-devel&nbsp;pcre-devel&nbsp;openssl&nbsp;openssl-devel&nbsp;&nbsp;</span><br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">执行完成后,然后<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">ls</code>查看目录文件,会看一大堆依赖:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.2046875" src="/upload/faf1241038e2e7115e4156b63a9bcc9a.jpg" data-w="640" style="margin-right: auto;margin-left: auto;outline: 0px;border-radius: 8px;display: block;background-size: 16px !important;width: 640px !important;visibility: visible !important;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">紧接着通过<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">rpm</code>命令依次将依赖包一个个构建,或者通过如下指令一键安装所有依赖包:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;rpm&nbsp;-ivh&nbsp;--nodeps&nbsp;*.rpm&nbsp;&nbsp;</span><br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">❺进入解压后的<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">nginx</code>目录,然后执行<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>的配置脚本,为后续的安装提前配置好环境,默认位于<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">/usr/local/nginx/</code>目录下(可自定义目录):</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;cd&nbsp;nginx-1.21.6&nbsp;&nbsp;</span><br style="outline: 0px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;./configure&nbsp;--prefix=/soft/nginx/&nbsp;&nbsp;</span><br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">❻编译并安装<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;make&nbsp;&amp;&amp;&nbsp;make&nbsp;install&nbsp;&nbsp;</span><br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">❼最后回到前面的<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">/soft/nginx/</code>目录,输入<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">ls</code>即可看见安装<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">nginx</code>完成后生成的文件。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">❽修改安装后生成的<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">conf</code>目录下的<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">nginx.conf</code>配置文件:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;vi&nbsp;conf/nginx.conf&nbsp;&nbsp;</span><br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;修改端口号:listen &nbsp;&nbsp; 80;&nbsp;&nbsp;<br style="outline: 0px;">&nbsp;修改IP地址:server_name &nbsp;你当前机器的本地IP(线上配置域名);&nbsp;&nbsp;<br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">❾制定配置文件并启动<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;sbin/nginx&nbsp;-c&nbsp;conf/nginx.conf&nbsp;&nbsp;</span><br style="outline: 0px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;ps&nbsp;aux&nbsp;|&nbsp;grep&nbsp;nginx&nbsp;&nbsp;</span><br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>其他操作命令:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">sbin/nginx&nbsp;-t&nbsp;-c&nbsp;conf/nginx.conf&nbsp;<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;检测配置文件是否正常&nbsp;&nbsp;</span><br style="outline: 0px;">sbin/nginx&nbsp;-s&nbsp;reload&nbsp;-c&nbsp;conf/nginx.conf&nbsp;<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;修改配置后平滑重启&nbsp;&nbsp;</span><br style="outline: 0px;">sbin/nginx&nbsp;-s&nbsp;quit&nbsp;<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;优雅关闭Nginx,会在执行完当前的任务后再退出&nbsp;&nbsp;</span><br style="outline: 0px;">sbin/nginx&nbsp;-s&nbsp;stop&nbsp;<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;强制终止Nginx,不管当前是否有任务在执行&nbsp;&nbsp;</span><br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">❿开放<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">80</code>端口,并更新防火墙:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;firewall-cmd&nbsp;--zone=public&nbsp;--add-port=80/tcp&nbsp;--permanent&nbsp;&nbsp;</span><br style="outline: 0px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;firewall-cmd&nbsp;--reload&nbsp;&nbsp;</span><br style="outline: 0px;">[root@localhost]<span style="outline: 0px;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">#&nbsp;firewall-cmd&nbsp;--zone=public&nbsp;--list-ports&nbsp;&nbsp;</span><br style="outline: 0px;"></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">⓫在<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Windows/Mac</code>的浏览器中,直接输入刚刚配置的<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">IP</code>地址访问<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">最终看到如上的<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>欢迎界面,代表<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">Nginx</code>安装完成。</p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 30px;outline: 0px;font-weight: bold;font-size: 22px;border-bottom: 2px solid rgb(89, 89, 89);color: rgb(89, 89, 89);"><strong><span style="outline: 0px;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);">三、Nginx反向代理-负载均衡</span></strong></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;outline: 0px;line-height: 26px;color: rgb(89, 89, 89);">首先通过<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">SpringBoot+Freemarker</code>快速搭建一个<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">WEB</code>项目:springboot-web-nginx,然后在该项目中,创建一个<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;outline: 0px;font-size: 14px;border-radius: 4px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(71, 193, 168);">IndexNginxController.java</code>文件,逻辑如下:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;"><code style="padding: 16px;outline: 0px;overflow-x: auto;color: rgb(171, 178, 191);background: rgb(40, 44, 52);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;"><span style="outline: 0px;color: rgb(97, 174, 238);line-height: 26px;">@Controller</span>&nbsp;&nbsp;<br style="outline: 0px;"><span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">public</span>&nbsp;<span style="outline: 0px;line-height: 26px;"><span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">class</span>&nbsp;<span style="outline: 0px;color: rgb(230, 192, 123);line-height: 26px;">IndexNginxController</span>&nbsp;</span>{&nbsp;&nbsp;<br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;color: rgb(97, 174, 238);line-height: 26px;">@Value</span>(<span style="outline: 0px;color: rgb(152, 195, 121);line-height: 26px;">"${server.port}"</span>)&nbsp;&nbsp;<br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;color: rgb(198, 120, 221);line-height: 26px;">private</span>&nbsp;String&nbsp;port;&nbsp;&nbsp;<br style="outline: 0px;">&nbsp;&nbsp;<br style="outline: 0px;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;color: rgb(97, 174, 238);line-height: 26px;">@RequestMapping</span>(<span style="outline: 0px;color: rgb(152, 195, 121);line-height: 26px;">"/"</span>)&nbsp;&nbsp;<br style="out

SpringBoot 通用限流方案!

作者:微信小助手

<section style="outline: 0px;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: auto;font-family: -apple-system-font, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;margin-bottom: 0px;"> <span style="outline: 0px;color: rgb(120, 114, 119);font-family: -apple-system-font, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;text-align: left;">作者:<span style="color: rgb(120, 114, 119);font-family: -apple-system-font, 'system-ui', 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;text-wrap: wrap;widows: 1;caret-color: rgb(51, 51, 51);background-color: rgb(255, 255, 255);">小码农叔叔</span></span> </section> <section style="outline: 0px;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: auto;font-family: -apple-system-font, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;margin-bottom: 0px;"> <span style="outline: 0px;color: rgb(120, 114, 119);font-family: -apple-system-font, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;text-align: left;">来源:<span style="color: rgb(120, 114, 119);font-family: -apple-system-font, 'system-ui', 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;text-wrap: wrap;widows: 1;caret-color: rgb(51, 51, 51);background-color: rgb(255, 255, 255);">blog.csdn.net/zhangcongyi420/article/details/131342759</span></span> <span style="outline: 0px;color: rgb(120, 114, 119);font-family: -apple-system-font, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;text-align: left;"></span> </section> <section style="outline: 0px;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);caret-color: rgb(51, 51, 51);text-size-adjust: auto;font-family: -apple-system-font, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif;margin-bottom: 0px;"> <br> </section> <h1 data-tool="mdnice编辑器" style="margin: 1.2em auto;outline: 0px;font-weight: bold;font-size: 1.8em;letter-spacing: normal;text-wrap: wrap;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;background-color: rgb(255, 255, 255);color: rgb(0, 150, 136);text-align: center;border-bottom: 1px solid rgb(0, 150, 136);">一、背景</h1> <p data-tool="mdnice编辑器" style="margin-bottom: 0px;padding-top: 8px;padding-bottom: 8px;outline: 0px;color: rgb(0, 0, 0);font-size: 16px;letter-spacing: normal;text-align: left;text-wrap: wrap;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;background-color: rgb(255, 255, 255);line-height: 26px;">限流对于一个微服务架构系统来说具有非常重要的意义,否则其中的某个微服务将成为整个系统隐藏的雪崩因素,为什么这么说?</p> <p data-tool="mdnice编辑器" style="margin-bottom: 0px;padding-top: 8px;padding-bottom: 8px;outline: 0px;color: rgb(0, 0, 0);font-size: 16px;letter-spacing: normal;text-align: left;text-wrap: wrap;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New

同一份数据,Redis为什么要存两次?

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-bottom: 0px;padding-right: 10px;padding-left: 10px;outline: 0px;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;visibility: visible;" data-mpa-powered-by="yiban.io"> <h2 data-tool="mdnice编辑器" style="margin-top: 2.2em;margin-bottom: 35px;outline: 0px;font-we

微服务最重要的10个设计模式

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;overflow-wrap: break-word;text-align: left;padding: 5px;font-size: 16px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;" data-mpa-powered-by="yiban.io"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;word-wrap: break-word;text-align: left;padding: 5px;font-size: 16px;color: #353535;word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;"><strong style="font-weight: 700;color: rgb(248, 57, 41);">大家好,我是不才陈某~</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;">从软件开发早期(1960 年代)开始,应对大型软件系统中的复杂性一直是一项令人生畏的任务。多年来为了应对软件系统的复杂性,软件工程师和架构师们做了许多尝试:David Parnas 的模块化和封装 (1972), Edsger W. Dijkstra (1974)的关注点分离以及 SOA(1988)</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;">他们都是使用分而治之这项成熟的传统技术来应对大型系统的复杂性。自 2010 年开始,这些技术被证实无法继续应对 Web 级应用或者现代大型企业级应用的复杂性。因此架构师和工程师们发展出了一种全新的现代方式来解决这个问题,就是微服务架构。它虽然延续了分而治之的思想,但却是以全新的方式来实现的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;">软件设计模式是解决软件设计中常见问题的通用、可复用的解决方案。设计模式让我们可以分享通用词汇并使用经实战检验的方案,以免重复造轮子。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;"><strong style="font-weight: 700;color: rgb(248, 57, 41);">通过阅读这篇文章,你会学到:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;list-style-type: disc;color: #f83929;font-size: 16px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 微服务架构。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 微服务架构的优势。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 微服务架构的劣势。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 何时使用微服务架构。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 最重要的微服务架构设计模式,包括其优缺点、用例、上下文、技术栈示例及可用资源。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;">请注意,本清单中的大部分设计模式常出现在多种语境中,并且可以在非微服务架构中使用。而我将在微服务这个特定语境中介绍它们。</p> <figure data-tool="mdnice编辑器" style="margin: 0;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.41574074074074074" data-type="png" data-w="1080" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/14551b50edafa11c00d8f9a1976d6b50.png"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 22px;text-align: left;margin: 20px 10px 0px 0px;"><span style="display: none;"></span><span style="font-size: 18px;font-weight: 700;color: #222;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: 0.8em 0;font-size: 16px;color: #353535;">那到底什么是微服务架构?有很多种定义方法。我的定义是这这样的:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;">微服务架构指的是将大型复杂系统按功能或者业务需求垂直切分成更小的子系统,这些子系统以独立部署的子进程存在,它们之间通过轻量级的、跨语言的同步(比如 REST,gRPC)或者异步(消息)网络调用进行通信。关注公号:码猿技术专栏,回复关键:1111 获取阿里内部Java性能调优手册</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;">下面是基于微服务架构的商业 Web 应用的组件视图:</p> <figure data-tool="mdnice编辑器" style="margin: 0;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.637599093997735" data-type="png" data-w="883" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/d463a6391a4be08e81899441e0e459b7.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;"><strong style="font-weight: 700;color: rgb(248, 57, 41);">微服务架构的重要特征:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;list-style-type: disc;color: #f83929;font-size: 16px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 整个应用程序被拆分成相互独立但包含多个内部模块的子进程。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 与模块化的单体应用(Modular Monoliths)或 SOA 相反,微服务应用程序根据业务范围或领域垂直拆分。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 微服务边界是外部的,微服务之间通过网络调用(RPC 或消息)相互通信。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 微服务是独立的进程,它们可以独立部署。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 它们以轻量级的方式进行通信,不需要任何智能通信通道。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;"><strong style="font-weight: 700;color: rgb(248, 57, 41);">微服务架构的优点:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;list-style-type: disc;color: #f83929;font-size: 16px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 更好的开发规模。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 更快的开发速度。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 支持迭代开发或现代化增量开发。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 充分利用现代软件开发生态系统的优势(云、容器、 DevOps、Serverless)。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 支持水平缩放和细粒度缩放。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 小体量,较低了开发人员的认知复杂性。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;"><strong style="font-weight: 700;color: rgb(248, 57, 41);">微服务架构的缺点:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;list-style-type: disc;color: #f83929;font-size: 16px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 更高数量级的活动组件(服务、数据库、进程、容器、框架)。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 复杂性从代码转移到基础设施。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> RPC 调用和网络通信的大量增加。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 整个系统的安全性管理更具有挑战性。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 整个系统的设计变得更加困难。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 引入了分布式系统的复杂性。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;"><strong style="font-weight: 700;color: rgb(248, 57, 41);">何时使用微服务架构:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;list-style-type: disc;color: #f83929;font-size: 16px;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 大规模 Web 应用开发。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 跨团队企业级应用协作开发。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 长期收益优先于短期收益。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-weight: 500;color: #353535;"> 团队拥有能够设计微服务架构的软件架构师或高级工程师。 </section></li> </ul> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;padding: 0px;font-weight: bold;color: black;font-size: 22px;text-align: left;margin: 20px 10px 0px 0px;"><span style="display: none;"></span><span style="font-size: 18px;font-weight: 700;color: #222;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;padding: 0px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">1. 独享数据库(Database per Microservice)</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;">当一家公司将大型单体系统替换成一组微服务,首先要面临的最重要决策是关于数据库。单体架构会使用大型中央数据库。即使转移到微服务架构许多架构师仍倾向于保持数据库不变。虽然有一些短期收益,但它却是反模式的,特别是在大规模系统中,微服务将在数据库层严重耦合,整个迁移到微服务的目标都将面临失败(例如,团队授权、独立开发等问题)。<span style="color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.8px;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0.8px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;display: inline !important;float: none;">关注公号:</span><span style="color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.8px;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0.8px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;display: inline !important;float: none;">码猿技术专栏,回复关键:</span><span style="color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.8px;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0.8px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;display: inline !important;float: none;">111</span><span style="color: rgb(53, 53, 53);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: 0.8px;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0.8px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;display: inline !important;float: none;">1 获取阿里内部Java性能调优手册</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;">更好的方法是为每个微服务提供自己的数据存储,这样服务之间在数据库层就不存在强耦合。这里我使用数据库这一术语来表示逻辑上的数据隔离,也就是说微服务可以共享物理数据库,但应该使用分开的数据结构、集合或者表,这还将有助于确保微服务是按照领域驱动设计的方法正确拆分的。</p> <figure data-tool="mdnice编辑器" style="margin: 0;margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.6202723146747352" data-type="png" data-w="661" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/e04200001e7a750f13f3c8e710e81b92.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin: 0.8em 0;font-size: 16px;color: #353535;"><strong style="font-weight: 700;color: rgb(248, 57, 41);">优点</strong></p> <ul data

高逼格的 SQL 写法:行行比较

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;padding: 5px;font-size: 16px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;" 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(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;"><span style="color: rgb(248, 57, 41);">环境准备</span></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">数据库版本:<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: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">MySQL 5.7.20-log</code></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.6021505376344086" data-w="279" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/6143dd1acc864309512728267fe44afb.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">建表 SQL</span></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oezBibiciavS1eDQSlYEgVoITJW44lH7o01jcEmepLMBzMadT5KicwlacY6omiaI60Iibwotd5nAAHQTaSaeswH0lPBNZp/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(255, 255, 255);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: black;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fff;border-radius: 5px;"><span style="color: #aa0d91;line-height: 26px;">DROP</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">TABLE</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">IF</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">EXISTS</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">`t_ware_sale_statistics`</span>;<br><span style="color: #aa0d91;line-height: 26px;">CREATE</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">TABLE</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">`t_ware_sale_statistics`</span>&nbsp;(<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`id`</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">bigint</span>(<span style="color: #1c00cf;line-height: 26px;">20</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">NOT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;AUTO_INCREMENT&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'主键id'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`business_id`</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">bigint</span>(<span style="color: #1c00cf;line-height: 26px;">20</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">NOT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'业务机构编码'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`ware_inside_code`</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">bigint</span>(<span style="color: #1c00cf;line-height: 26px;">20</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">NOT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'商品自编码'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`weight_sale_cnt_day`</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">double</span>(<span style="color: #1c00cf;line-height: 26px;">16</span>,<span style="color: #1c00cf;line-height: 26px;">4</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'平均日销量'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`last_thirty_days_sales`</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">double</span>(<span style="color: #1c00cf;line-height: 26px;">16</span>,<span style="color: #1c00cf;line-height: 26px;">4</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'最近30天销量'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`last_sixty_days_sales`</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">double</span>(<span style="color: #1c00cf;line-height: 26px;">16</span>,<span style="color: #1c00cf;line-height: 26px;">4</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'最近60天销量'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`last_ninety_days_sales`</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">double</span>(<span style="color: #1c00cf;line-height: 26px;">16</span>,<span style="color: #1c00cf;line-height: 26px;">4</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'最近90天销量'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`same_period_sale_qty_thirty`</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">double</span>(<span style="color: #1c00cf;line-height: 26px;">16</span>,<span style="color: #1c00cf;line-height: 26px;">4</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'去年同期30天销量'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`same_period_sale_qty_sixty`</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">double</span>(<span style="color: #1c00cf;line-height: 26px;">16</span>,<span style="color: #1c00cf;line-height: 26px;">4</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'去年同期60天销量'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`same_period_sale_qty_ninety`</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">double</span>(<span style="color: #1c00cf;line-height: 26px;">16</span>,<span style="color: #1c00cf;line-height: 26px;">4</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'去年同期90天销量'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`create_user`</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">bigint</span>(<span style="color: #1c00cf;line-height: 26px;">20</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'创建人'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`create_time`</span>&nbsp;datetime&nbsp;<span style="color: #aa0d91;line-height: 26px;">NOT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">CURRENT_TIMESTAMP</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'创建时间'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`modify_user`</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">bigint</span>(<span style="color: #1c00cf;line-height: 26px;">20</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'最终修改人'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`modify_time`</span>&nbsp;datetime&nbsp;<span style="color: #aa0d91;line-height: 26px;">NOT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">NULL</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">CURRENT_TIMESTAMP</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">ON</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">UPDATE</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">CURRENT_TIMESTAMP</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'最终修改时间'</span>,<br>&nbsp;&nbsp;<span style="color: #c41a16;line-height: 26px;">`is_delete`</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">tinyint</span>(<span style="color: #1c00cf;line-height: 26px;">2</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'2'</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">'是否删除,1:是,2:否'</span>,<br>&nbsp;&nbsp;PRIMARY&nbsp;<span style="color: #aa0d91;line-height: 26px;">KEY</span>&nbsp;(<span style="color: #c41a16;line-height: 26px;">`id`</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">USING</span>&nbsp;BTREE,<br>&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">KEY</span>&nbsp;<span style="color: #c41a16;line-height: 26px;">`idx_business_ware`</span>&nbsp;(<span style="color: #c41a16;line-height: 26px;">`business_id`</span>,<span style="color: #c41a16;line-height: 26px;">`ware_inside_code`</span>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">USING</span>&nbsp;BTREE<br>)&nbsp;<span style="color: #aa0d91;line-height: 26px;">ENGINE</span>=<span style="color: #aa0d91;line-height: 26px;">InnoDB</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">DEFAULT</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">CHARSET</span>=utf8mb4&nbsp;ROW_FORMAT=DYNAMIC&nbsp;<span style="color: #aa0d91;line-height: 26px;">COMMENT</span>=<span style="color: #c41a16;line-height: 26px;">'商品销售统计'</span>;<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">初始化数据</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">准备了 769063 条数据</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.45454545454545453" data-w="418" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/de3955da0f212a251fade6ead2cbfc7c.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">需求背景</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">业务机下销售商品,同个业务机构可以销售不同的商品,同个商品可以在不同的业务机构销售,也就说:业务机构与商品是多对多的关系</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">假设现在有 n 个机构,每个机构下有几个商品,如何查询出这几个门店下各自商品的销售情况?</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 class="rich_pages wxw-img" data-ratio="0.5762962962962963" data-w="675" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/7912542fe186bfb30d2fc9bdca6d3e4e.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">如何查出 100001 下商品 1000、1001、1003 、 100002 下商品 1003、1004 、 100003 下商品 1006、1008、1009 的销售情况</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> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);border-left-width: 2px;padding: 8px 10px 8px 15px;background: rgb(255, 249, 249);border-left-color: rgb(239, 112, 96);margin-top: 0px;margin-bottom: 20px;letter-spacing: 0.5444px;"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(53, 53, 53);font-size: 16px;margin-right: 10px;margin-left: 10px;">问题经我一描述,可能更模糊了,大家明白意思了就好!</p> </blockquote> <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 class="rich_pages wxw-img" data-ratio="0.22955974842767296" data-w="636" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/9d507d3f9dbbaaf7cd66a4ffca5aea5e.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">具体的 SQL 类似如下</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.3742690058479532" data-w="342" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/3bb9810a141c866bdd1c5ea55035f94e.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">SQL 能走索引</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.195496417604913" data-w="977" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/98b9c3cb3abba4dd05c1aa4fd43bef13.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">实现简单,也好理解,SQL 也能走索引,一切看起来似乎很完美</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> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">OR 拼接</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">通过 MyBatis 的 动态 SQL 功能,进行 SQL 拼接,类似如下</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.24660397074190177" data-w="957" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/bb1ffdb5b250a5adcd61cae039fe912.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">具体的 SQL 类似如下</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.20738636363636365" data-w="704" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/4d7b889249862172cf2013e0a8eaee91.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">SQL 也能走索引</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.19237918215613384" data-w="1076" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/ea8585ed082faac463ac8b09528a394.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">实现简单,也好理解,SQL 也能走索引,而且只查询一次数据库,貌似可行</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">唯一可惜的是:有点费 OR,如果业务机构比较多,那 SQL 会比较长</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">作为候选人之一吧,我们接着往下看</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">混查过滤</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">同样是利用 Mybatis 的 动态 SQL ,将 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">business_id</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: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">ware_inside_code</code> 拼在一起,类似如下</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.2783018867924528" data-w="848" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/421c527dbe35798b448e5623674c0c85.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">具体的 SQL 类似如下</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.29493087557603687" data-w="434" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/992c738a3da542485d4af9b9e89ba92b.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">SQL 也能走索引</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.18238341968911917" data-w="965" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/34016b6151780a10220d02d66fc00504.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">实现简单,也好理解,SQL 也能走索引,而且只查询一次数据库,似乎可行</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> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">姑且也作为候选人之一吧,我们继续往下看</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">行行比较</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">SQL-92 中加入了行与行比较的功能,这样一来,比较谓词 = 、&lt; 、&gt; 和 IN 谓词的参数就不再只是标量值了,还可以是值列表了</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">当然,还是得用到 Mybatis 的 动态 SQL ,类似如下</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.28440366972477066" data-w="654" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/ce7e0c46b31de45525627988ca6fcb8a.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">具体的 SQL 类似如下</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.191044776119403" data-w="670" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/82d391da690557a1c44ef9b6a402322f.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">SQL 同样能走索引</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.18518518518518517" data-w="972" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/28b476fd4f6f095b0aa812d1ac93b393.png"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">实现简单,SQL 也能走索引,而且只查询一次数据库,感觉可行</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;">另外,行行比较是 SQL 规范,不是某个关系型数据库的规范,也就说关系型数据库都应该支持这种写法</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;"><span style="color: rgb(248, 57, 41);">总结</span></span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">1、最后选择了 行行比较 这种方式来实现了需求</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">别问我为什么,问就是逼格高!</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">2、某一个需求的实现往往有很多种方式,我们需要结合业务以及各种约束综合考虑,选择最合适的那个</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">3、行行比较是 SQL-92 中引入的,SQL-92 是 1992 年制定的规范</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">行行比较不是新特性,而是很早就存在的基础功能!</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);border-left-width: 2px;padding: 8px 10px 8px 15px;background: rgb(255, 249, 249);border-left-color: rgb(239, 112, 96);margin-top: 0px;margin-bottom: 20px;letter-spacing: 0.5444px;"></blockquote> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"></figure> </section>

程序员必须要知道的编程范式,你掌握了吗?

作者:微信小助手

<p style="text-align: center;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.625" data-s="300,640" data-type="jpeg" data-w="1024" style="height: auto !important;" src="/upload/c0c07e743e9ff813a8ca2b249cf57172.jpg"></p> <section style="font-size: 15px;"> <section style="text-align: left;justify-content: flex-start;display: flex;flex-flow: row nowrap;margin-top: 10px;margin-bottom: 10px;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;vertical-align: top;align-self: flex-start;flex: 0 0 auto;background-color: rgba(62, 62, 62, 0.04);padding: 31px;"> <section style="text-align: center;justify-content: center;display: flex;flex-flow: row nowrap;margin-bottom: 10px;" powered-by="xiumi.us"> <section style="display: inline-block;vertical-align: top;width: 33.33%;"> <section style="margin-top: 11px;margin-bottom: 8px;" powered-by="xiumi.us"> <section style="background-color: rgba(62, 62, 62, 0.66);height: 1px;"> <svg viewbox="0 0 1 1" style="float:left;line-height:0;width:0;vertical-align:top;"></svg> </section> </section> </section> <section style="display: inline-block;vertical-align: top;width: auto;align-self: flex-start;flex: 0 0 auto;min-width: 5%;height: auto;padding-right: 14px;padding-left: 14px;"> <section style="text-align: justify;font-size: 11px;color: rgba(62, 62, 62, 0.66);" powered-by="xiumi.us"> <p style="white-space: normal;">阿里妹导读</p> </section> <section style="transform: rotateZ(45deg);" powered-by="xiumi.us"> <section style="transform: translate3d(-6px, 0px, 0px);margin-top: 6px;"> <section style="display: inline-block;width: 15px;height: 15px;vertical-align: top;overflow: hidden;border-style: solid;border-width: 0px 3px 3px 0px;border-color: rgb(195, 5, 3) rgb(255, 129, 36) rgb(255, 129, 36) rgb(195, 5, 3);"> <section style="text-align: justify;" powered-by="xiumi.us"> <p style="white-space: normal;"><br></p> </section> </section> </section> </section> </section> <section style="display: inline-block;vertical-align: top;width: 33.33%;"> <section style="margin-top: 11px;margin-bottom: 8px;" powered-by="xiumi.us"> <section style="background-color: rgba(62, 62, 62, 0.66);height: 1px;"> <svg viewbox="0 0 1 1" style="float:left;line-height:0;width:0;vertical-align:top;"></svg> </section> </section> </section> </section> <section style="text-align: center;" powered-by="xiumi.us"> <section style="text-align: justify;"> <section style="white-space: normal;line-height: 1.75em;"> <span style="color: rgb(136, 136, 136);font-size: 14px;">本文给大家介绍了什么是<span style="font-size: 14px;color: rgb(136, 136, 136);letter-spacing: 0.578px;">"编程范式",<span style="font-size: 14px;color: rgb(136, 136, 136);letter-spacing: 0.578px;">选择合适的编程范式可以提高代码的可读性、可维护性和可扩展性。</span></span></span> </section> </section> </section> </section> </section> </section> <section style="font-size: 15px;"> <section style="margin-top: 10px;margin-bottom: 10px;text-align: center;" powered-by="xiumi.us"> <section style="padding: 3px;display: inline-block;border-bottom: 5px solid rgb(255, 129, 36);color: rgb(255, 129, 36);font-size: 16px;"> <p>一、 什么是编程范式?</p> </section> </section> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);">"编程范式"是一种<strong>编程思想</strong>的总称,它是指在编写程序时所采用的基本方法和规范。常见的编程范式有面向对象、函数式、逻辑式等。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);">选择合适的编程范式可以提高代码的可读性、可维护性和可扩展性,是程序员必备的基本技能之一。</span> </section> <section style="font-size: 15px;"> <section style="margin-top: 10px;margin-bottom: 10px;text-align: center;" powered-by="xiumi.us"> <section style="padding: 3px;display: inline-block;border-bottom: 5px solid rgb(255, 129, 36);color: rgb(255, 129, 36);font-size: 16px;"> <p>二、常见的编程范式</p> </section> </section> </section> <h1 style="line-height: 1.75em;"><span style="font-size: 15px;color: rgb(62, 62, 62);"></span></h1> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);">以下是常见的编程范式:</span> </section> <ul class="list-paddingleft-1" style="list-style-type: revert;"> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 8px;"><strong><span style="font-size: 15px;color: rgb(62, 62, 62);">命令式编程</span></strong><span style="font-size: 15px;color: rgb(62, 62, 62);">(Imperative Programming):以指令的形式描述计算机执行的具体步骤,关注计算机的状态变化和控制流程。典型代表语言:C、Java。</span></p></li> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 8px;"><strong><span style="font-size: 15px;color: rgb(62, 62, 62);">面向对象编程</span></strong><span style="font-size: 15px;color: rgb(62, 62, 62);">(Object-Oriented Programming):将程序组织为对象的集合,强调数据和操作的封装、继承和多态。典型代表语言:Java、C++、Python。</span></p></li> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 8px;"><strong><span style="font-size: 15px;color: rgb(62, 62, 62);">函数式编程</span></strong><span style="font-size: 15px;color: rgb(62, 62, 62);">(Functional Programming):将计算视为数学函数的求值,强调使用纯函数、不可变数据和高阶函数。典型代表语言:Haskell、Clojure、Scala。</span></p></li> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 8px;"><strong><span style="font-size: 15px;color: rgb(62, 62, 62);">声明式编程</span></strong><span style="font-size: 15px;color: rgb(62, 62, 62);">(Declarative Programming):以描述问题的本质和解决方案的逻辑为重点,而非具体的计算步骤。包括逻辑编程、函数式编程、数据流编程等。典型代表语言:Prolog、SQL、HTML/CSS。</span></p></li> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 8px;"><strong><span style="font-size: 15px;color: rgb(62, 62, 62);">逻辑编程</span></strong><span style="font-size: 15px;color: rgb(62, 62, 62);">(Logic Programming):使用逻辑表达式描述问题和解决方案,基于逻辑推理进行计算。典型代表语言:Prolog。</span></p></li> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 8px;"><strong><span style="font-size: 15px;color: rgb(62, 62, 62);">并发编程</span></strong><span style="font-size: 15px;color: rgb(62, 62, 62);">(Concurrent Programming):处理多个并发执行的任务,关注并发、并行、同步和通信等问题。典型代表语言:Java、Go、Erlang。</span></p></li> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 8px;"><strong><span style="font-size: 15px;color: rgb(62, 62, 62);">泛型编程</span></strong><span style="font-size: 15px;color: rgb(62, 62, 62);">(Generic Programming):通过参数化类型来实现代码的复用和抽象,提供通用的数据结构和算法。典型代表语言:C++、Rust。</span></p></li> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 8px;"><strong><span style="font-size: 15px;color: rgb(62, 62, 62);">面向切面编程</span></strong><span style="font-size: 15px;color: rgb(62, 62, 62);">(Aspect-Oriented Programming):将横切关注点(如日志、事务管理)从主要逻辑中分离出来,以提供更好的模块化和可维护性。典型代表框架:AspectJ。</span></p></li> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 24px;"><strong><span style="font-size: 15px;color: rgb(62, 62, 62);">响应式编程</span></strong><span style="font-size: 15px;color: rgb(62, 62, 62);">(Reactive Programming):通过使用流(Stream)和异步事件来处理数据流和事件流,使程序能够以响应式、弹性和容错的方式进行处理。典型代表框架:RxJava、Reactor。</span></p></li> </ul> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);">这些编程范式具有不同的思维方式、原则和技术,适用于不同的问题和场景。在实际开发中,可以根据需求和团队的偏好选择合适的编程范式或结合多种范式来实现目标。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);">需要注意的是,并非每种编程语言都完全支持所有编程范式,有些语言可能更加倾向于某种特定的范式。此外,随着技术的发展,新的编程范式也在不断涌现,扩展了编程的思维和能力。</span> </section> <section style="font-size: 15px;"> <section style="margin-top: 10px;margin-bottom: 10px;text-align: center;" powered-by="xiumi.us"> <section style="padding: 3px;display: inline-block;border-bottom: 5px solid rgb(255, 129, 36);color: rgb(255, 129, 36);font-size: 16px;"> <p>三、各大编程范式详解</p> </section> </section> </section> <h1 style="line-height: 1.75em;"><span style="font-size: 15px;color: rgb(62, 62, 62);"></span></h1> <section style="font-size: 15px;"> <section style="text-align: left;justify-content: flex-start;margin: 10px 0%;display: flex;flex-flow: row nowrap;" powered-by="xiumi.us"> <section style="display: inline-block;vertical-align: bottom;width: auto;align-self: flex-end;flex: 0 0 0%;height: auto;line-height: 0;"> <section style="text-align: right;" powered-by="xiumi.us"> <section style="display: inline-block;width: 18px;height: 18px;vertical-align: top;overflow: hidden;background-color: rgb(255, 129, 36);"> <svg viewbox="0 0 1 1" style="float:left;line-height:0;width:0;vertical-align:top;"></svg> </section> </section> </section> <section style="display: inline-block;vertical-align: bottom;width: auto;min-width: 10%;flex: 0 0 auto;height: auto;align-self: flex-end;"> <section style="color: rgb(62, 62, 62);font-size: 14px;padding-right: 4px;padding-left: 4px;line-height: 1;text-align: justify;" powered-by="xiumi.us"> <p style="white-space: normal;"><br></p> <p style="white-space: normal;"><strong><span style="font-size: 15px;">3.1 命令式编程</span></strong></p> </section> </section> <section style="display: inline-block;vertical-align: middle;width: auto;align-self: center;min-width: 10%;flex: 0 0 auto;height: auto;line-height: 0;"> <svg viewbox="0 0 1 1" style="float:left;line-height:0;width:0;vertical-align:top;"></svg> </section> </section> </section> <h2 style="line-height: 1.75em;"><span style="font-size: 15px;color: rgb(62, 62, 62);"></span></h2> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);">命令式编程是一种以指令的形式描述计算机执行的具体步骤的编程范式。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);">在命令式编程中,开发人员需要逐步指定计算机执行的操作,包括数据的获取、处理和存储等。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);">这种编程范式关注计算机的状态变化和控制流程,通过改变状态和控制流程来实现所需的计算目标。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);">下面是一个使用 Java 语言的简单示例,展示了命令式编程的特点:</span> </section> <pre> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="cs"><code><span class="code-snippet_outer"><span class="code-snippet__keyword">public</span> <span class="code-snippet__keyword">class</span> <span class="code-snippet__title">CommandExample</span> {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__function"><span class="code-snippet__keyword">public</span> <span class="code-snippet__keyword">static</span> <span class="code-snippet__keyword">void</span> <span class="code-snippet__title">main</span>(<span class="code-snippet__params">String[] args</span>)</span> {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">int</span> num1 = <span class="code-snippet__number">5</span>;</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">int</span> num2 = <span class="code-snippet__number">10</span>;</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">int</span> sum = <span class="code-snippet__number">0</span>;</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 计算两个数的和</span></span></code><code><span class="code-snippet_outer"> sum = num1 + num2;</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment">// 打印结果</span></span></code><code><span class="code-snippet_outer"> System.<span class="code-snippet__keyword">out</span>.println(<span class="code-snippet__string">"Sum: "</span> + sum);</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer">}</span></code></pre> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);"><br></span> </section></pre> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);">在上面的示例中,我们通过逐步指定计算机执行的操作来实现两个数的相加,并将结果打印出来。具体步骤如下:</span> </section> <ol class="list-paddingleft-1" style="list-style-type: revert;"> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 8px;"><span style="font-size: 15px;color: rgb(62, 62, 62);">声明变量</span><span style="font-size: 15px;background-color: rgb(245, 245, 245);color: rgb(136, 136, 136);">num1</span><span style="font-size: 15px;color: rgb(62, 62, 62);">和</span><span style="font-size: 15px;background-color: rgb(245, 245, 245);color: rgb(136, 136, 136);">num2</span><span style="font-size: 15px;color: rgb(62, 62, 62);">,并初始化为5和10。</span></p></li> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 8px;"><span style="font-size: 15px;color: rgb(62, 62, 62);">声明变量</span><span style="font-size: 15px;background-color: rgb(245, 245, 245);color: rgb(136, 136, 136);">sum</span><span style="font-size: 15px;color: rgb(62, 62, 62);">,用于存储计算结果。</span></p></li> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 8px;"><span style="font-size: 15px;color: rgb(62, 62, 62);">执行相加操作</span><span style="font-size: 15px;background-color: rgb(245, 245, 245);color: rgb(136, 136, 136);">num1 + num2</span><span style="font-size: 15px;color: rgb(62, 62, 62);">,将结果赋值给</span><span style="font-size: 15px;background-color: rgb(245, 245, 245);color: rgb(136, 136, 136);">sum</span><span style="font-size: 15px;color: rgb(62, 62, 62);">。</span></p></li> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 24px;"><span style="font-size: 15px;color: rgb(62, 62, 62);">使用</span><span style="font-size: 15px;background-color: rgb(245, 245, 245);color: rgb(136, 136, 136);">System.out.println</span><span style="font-size: 15px;color: rgb(62, 62, 62);">打印结果。</span></p></li> </ol> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);">这个示例展示了命令式编程的特点,即通过一系列的命令来改变计算机的状态(变量的赋值)和控制流程(指令的顺序执行)。开发人员需要显式地指定每个操作的细节,以实现所需的计算逻辑。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);">命令式编程的优点包括:</span> </section> <ul class="list-paddingleft-1" style="list-style-type: revert;"> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 8px;"><strong><span style="font-size: 15px;color: rgb(62, 62, 62);">直观性</span></strong><span style="font-size: 15px;color: rgb(62, 62, 62);">:命令式代码往往更容易理解和调试,因为操作和执行顺序直接可见。</span></p></li> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 24px;"><strong><span style="font-size: 15px;color: rgb(62, 62, 62);">灵活性</span></strong><span style="font-size: 15px;color: rgb(62, 62, 62);">:命令式编程允许开发人员精确控制计算机的状态和行为,适用于各种复杂的计算任务。</span></p></li> </ul> <section style="line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(62, 62, 62);">然而,命令式编程也存在一些缺点:</span> </section> <ul class="list-paddingleft-1" style="list-style-type: revert;"> <li style="font-size: 15px;color: rgb(62, 62, 62);"><p style="line-height: 1.75em;margin-bottom: 8px;"><strong><span style="font-size: 15px;color: rgb(62, 62, 62);">复杂性</span></strong><span style="font-size: 15px;color: rgb(62, 62, 62);">:随着程序规模的增长,命令式代码可能变得冗长、复杂,难�