文章列表

IntelliJ IDEA无法预览Markdown文件

作者:じ☆ve不哭

> IDEA plugin Markdown在插件启用的状态下无法渲染preview,显示空白。 ## 解决方法 在idea的安装目录下bin路径下找到idea.properties文件,并在最后加上如下配置 ``` ide.browser.jcef.gpu.disable=true ``` **主要是因为开发环境没有gpu硬件支持导致的!!!**

微服务的灰度发布就该这样设计~

作者:微信小助手

<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;">实际生产中如有需求变更,并不会直接更新线上服务,最通常的做法便是:切出线上的小部分流量进行体验测试,经过测试后无问题则全面的上线。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这样做的好处也是非常明显,一旦出现了BUG,能够保证大部分的客户端正常使用。</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 style="text-align: center;margin-bottom: 0em;padding: 0px 0.5em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.6094316807738815" data-s="300,640" src="/upload/30fd2eca904a8e533c049b10b5825b15.png" data-type="png" data-w="827" style="box-shadow: rgb(210, 210, 210) 0em 0em 0.5em 0px;font-size: 17px;"></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(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">什么是灰度发布?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。</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(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">为什么是全链路灰度发布?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">在陈某前面一篇文章有介绍到<span style="font-weight: 700;color: rgb(248, 57, 41);">网关的灰度发布</span>实现,仅仅是实现了<span style="font-weight: 700;color: rgb(248, 57, 41);">网关路由转发</span>的灰度发布,如下图:</p> <p style="text-align: center;margin-bottom: 0em;padding: 0px 0.5em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.43174924165824063" data-s="300,640" src="/upload/88b0056148902f100d38ad53791c1b3b.png" data-type="png" data-w="989" style="box-shadow: rgb(210, 210, 210) 0em 0em 0.5em 0px;font-size: 17px;"></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;"></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>路由到<span style="font-weight: 700;color: rgb(248, 57, 41);">文章服务B</span>(灰度服务),至于从文章服务B到评论服务是通过<span style="font-weight: 700;color: rgb(248, 57, 41);">openFeign</span>内部调用的,默认无法实现灰度标记<span style="font-weight: 700;color: rgb(248, 57, 41);">grayTag</span>的透传,因此文章服务B最终调用的是评论服务A,并不是评论服务B。</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> <ol 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);"> 网关通过灰度标记将部分流量转发给 <span style="font-weight: 700;color: rgb(248, 57, 41);">文章服务B</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 文章服务B能够实现灰度标记 <span style="font-weight: 700;color: rgb(248, 57, 41);">grayTag</span>的透传,最终调用 <span style="font-weight: 700;color: rgb(248, 57, 41);">评论服务B</span> </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">经过以上分析,全链路灰度发布需要实现两个点:</p> <ol 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);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">网关</span>路由转发实现灰度发布 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 服务内部通过 <span style="font-weight: 700;color: rgb(248, 57, 41);">openFeign</span>调用实现灰度发布(透传灰度标记 <span style="font-weight: 700;color: rgb(248, 57, 41);">grayTag</span>)。 </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">下面将以陈某的<a href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247506948&amp;idx=1&amp;sn=34e282405b10d075bb3e05cfb69663c5&amp;chksm=fcf703c9cb808adf321e465da578dc7dcf97aa90bd97639532af56dd8d619e96c34aef7c4b97&amp;token=581489813&amp;lang=zh_CN&amp;scene=21#wechat_redirect" style="color: rgb(248, 57, 41);border-bottom: 1px solid rgb(248, 57, 41);" data-linktype="2">《Spring Cloud Alibaba实战》</a>专栏中的服务为例进行灰度发布配置。</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(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">网关层的灰度路由转发</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">本篇文章将使用<span style="font-weight: 700;color: rgb(248, 57, 41);">Ribbon+Spring Cloud Gateway</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> <ol 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);"> 在网关的全局过滤器中根据业务规则给流量打上灰度标记 </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);"> 改造Ribbon负载均衡策略,根据流量标记从注册中心获取灰度服务 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 请求路由转发 </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">第一个问题:根据什么条件打上灰度标记?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这个需要根据实际的业务需要,比如根据用户所在的地区、使用客户端类型、随机截取流量.....</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这里我将直接使用一个标记<span style="font-weight: 700;color: rgb(248, 57, 41);">grayTag</span>,只要客户端请求头中携带了这个参数,并且设置为true,则走灰度发布逻辑。</p> <blockquote data-tool="mdnice编辑器" style="border-width: initial;border-style: none;border-color: initial;font-size: 0.9em;overflow: auto;margin-bottom: 20px;margin-top: 20px;padding-top: 15px;padding-right: 10px;padding-bottom: 15px;line-height: 1.75;border-radius: 13px;color: rgb(53, 53, 53);background: rgb(245, 245, 245);"> <span style="display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;font-size: 16px;margin-right: 10px;margin-left: 10px;">请求头中携带:grayTag=true</p> <span style="float: right;display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">”</span> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">第二个问题:为什么要在请求头中添加灰度标记传递给下游服务?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这一步非常关键,实现灰度标记透传给下游服务的关键,将灰度标记放在请求头中,下游服务只需要从请求头中获取灰度标记便知道是否是灰度发布,这个和令牌中继一个原理。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">第三个问题:灰度标记如何请求隔离?</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;">Spring MVC中的每个请求都是开启一个线程进行处理,因此可以将灰度标记放置在<span style="font-weight: 700;color: rgb(248, 57, 41);">ThreadLocal</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);">第四个问题:如何知道注册中心的服务哪个是灰度服务?</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;">Nacos支持在服务中配置一些元数据,可以将灰度标记配置在元数据中,这样就能区分哪些是灰度服务,哪些是正常服务。</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;">比如我的<a href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247506948&amp;idx=1&amp;sn=34e282405b10d075bb3e05cfb69663c5&amp;chksm=fcf703c9cb808adf321e465da578dc7dcf97aa90bd97639532af56dd8d619e96c34aef7c4b97&amp;token=581489813&amp;lang=zh_CN&amp;scene=21#wechat_redirect" style="color: rgb(248, 57, 41);border-bottom: 1px solid rgb(248, 57, 41);" data-linktype="2">《Spring Cloud Alibaba实战》</a>中涉及的一条调用链路如下图:</p> <p style="text-align: center;margin-bottom: 0em;padding: 0px 0.5em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.4302788844621514" data-s="300,640" src="/upload/da40f07dd278c891ae5f6df09296e831.png" data-type="png" data-w="753" style="box-shadow: rgb(210, 210, 210) 0em 0em 0.5em 0px;font-size: 17px;"></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;"></figure> <blockquote data-tool="mdnice编辑器" style="border-width: initial;border-style: none;border-color: initial;font-size: 0.9em;overflow: auto;margin-bottom: 20px;margin-top: 20px;padding-top: 15px;padding-right: 10px;padding-bottom: 15px;line-height: 1.75;border-radius: 13px;color: rgb(53, 53, 53);background: rgb(245, 245, 245);"> <span style="display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;font-size: 16px;margin-right: 10px;margin-left: 10px;"><span style="font-weight: 700;color: rgb(248, 57, 41);">需求</span>:现在只对<span style="font-weight: 700;color: rgb(248, 57, 41);">文章服务</span>、<span style="font-weight: 700;color: rgb(248, 57, 41);">评论服务</span>进行灰度发布,其他服务依然使用线上正在运行的服务</p> <span style="float: right;display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">”</span> </blockquote> <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 style="text-align: center;margin-bottom: 0em;padding: 0px 0.5em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.3563096500530223" data-s="300,640" src="/upload/9a905b86aee2fb92eab135ef434a6039.png" data-type="png" data-w="943" style="box-shadow: rgb(210, 210, 210) 0em 0em 0.5em 0px;font-size: 17px;"></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;"></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> <blockquote data-tool="mdnice编辑器" style="border-width: initial;border-style: none;border-color: initial;font-size: 0.9em;overflow: auto;margin-bottom: 20px;margin-top: 20px;padding-top: 15px;padding-right: 10px;padding-bottom: 15px;line-height: 1.75;border-radius: 13px;color: rgb(53, 53, 53);background: rgb(245, 245, 245);"> <span style="display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;font-size: 16px;margin-right: 10px;margin-left: 10px;">很简单:只需要将自定义的Ribbon灰度发布规则只对文章服务生效。</p> <span style="float: right;display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">”</span> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这里涉及到Ribbon中的一个注解:<span style="font-weight: 700;color: rgb(248, 57, 41);">@RibbonClients</span> ,只需要在其中的value属性指定需要生效的服务名称,那么此时网关中的配置如下:</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/A7sq8BD8oexqmcDw0weKQeLicSXAich7jG16eyUm2W9VdeU7Z0qCf64Ymcsl1fpvAaWXhhAHibzYgw7ESqMqYpVVItwtialU7BnO/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #383a42;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fafafa;border-radius: 5px;"><span style="color: #4078f2;line-height: 26px;">@RibbonClients</span>(value&nbsp;={<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//只对文章服务进行灰度发布</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #4078f2;line-height: 26px;">@RibbonClient</span>(value&nbsp;=&nbsp;<span style="color: #50a14f;line-height: 26px;">"article-server"</span>,configuration&nbsp;=&nbsp;GrayRuleConfig<span style="line-height: 26px;">.<span style="color: #a626a4;line-height: 26px;">class</span>)<br>}&nbsp;)<br>@<span style="color: #c18401;line-height: 26px;">SpringBootApplication</span><br><span style="color: #c18401;line-height: 26px;">public</span>&nbsp;<span style="color: #c18401;line-height: 26px;">class</span>&nbsp;<span style="color: #c18401;line-height: 26px;">GatewayApplication</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;<br>}<br><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">@RibbonClient</span>可以指定多个,这个注解有如下两个属性:</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);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">value</span>:指定服务的名称,在注册中心配置的服务名称 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">configuration</span>:自定义的负载均衡策略,这里是灰度发布的策略 </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;"><span style="font-weight: 700;color: rgb(248, 57, 41);">@RibbonClients</span>其中有一个属性<span style="font-weight: 700;color: rgb(248, 57, 41);">defaultConfiguration</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);">第六个问题:说了这么多,具体如何实现?</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);">全局过滤器</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/A7sq8BD8oexqmcDw0weKQeLicSXAich7jG16eyUm2W9VdeU7Z0qCf64Ymcsl1fpvAaWXhhAHibzYgw7ESqMqYpVVItwtialU7BnO/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #383a42;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fafafa;border-radius: 5px;"><span style="color: #a626a4;line-height: 26px;">public</span>&nbsp;<span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">class</span>&nbsp;<span style="color: #c18401;line-height: 26px;">GlobalGrayFilter</span>&nbsp;<span style="color: #a626a4;line-height: 26px;">implements</span>&nbsp;<span style="color: #c18401;line-height: 26px;">GlobalFilter</span></span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #4078f2;line-height: 26px;">@Override</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">public</span>&nbsp;Mono&lt;Void&gt;&nbsp;<span style="color: #4078f2;line-height: 26px;">filter</span><span style="line-height: 26px;">(ServerWebExchange&nbsp;exchange,&nbsp;GatewayFilterChain&nbsp;chain)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//①&nbsp;解析请求头,查看是否存在灰度发布的请求头信息,如果存在则将其放置在ThreadLocal中</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpHeaders&nbsp;headers&nbsp;=&nbsp;exchange.getRequest().getHeaders();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">if</span>&nbsp;(headers.containsKey(GrayConstant.GRAY_HEADER)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;gray&nbsp;=&nbsp;headers.getFirst(GrayConstant.GRAY_HEADER);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">if</span>&nbsp;(StrUtil.equals(gray,GrayConstant.GRAY_VALUE)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//②设置灰度标记</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GrayRequestContextHolder.setGrayTag(<span style="color: #a626a4;line-height: 26px;">true</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;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//③&nbsp;将灰度标记放入请求头中</span><br>&nbsp;&nbsp;&nbsp;ServerHttpRequest&nbsp;tokenRequest&nbsp;=&nbsp;exchange.getRequest().mutate()<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//将灰度标记传递过去</span><br>&nbsp;&nbsp;&nbsp;&nbsp;.header(GrayConstant.GRAY_HEADER,GrayRequestContextHolder.getGrayTag().toString())<br>&nbsp;&nbsp;&nbsp;&nbsp;.build();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServerWebExchange&nbsp;build&nbsp;=&nbsp;exchange.mutate().request(tokenRequest).build();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">return</span>&nbsp;chain.filter(build);<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;"><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;"><span style="font-weight: 700;color: rgb(248, 57, 41);">②处的代码</span>:<span style="font-weight: 700;color: rgb(248, 57, 41);">GrayRequestContextHolder</span>则是自定义的ThreadLocal实现的线程隔离工具,用来存放灰度标记</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> <blockquote data-tool="mdnice编辑器" style="border-width: initial;border-style: none;border-color: initial;font-size: 0.9em;overflow: auto;margin-bottom: 20px;margin-top: 20px;padding-top: 15px;padding-right: 10px;padding-bottom: 15px;line-height: 1.75;border-radius: 13px;color: rgb(53, 53, 53);background: rgb(245, 245, 245);"> <span style="display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;font-size: 16px;margin-right: 10px;margin-left: 10px;">注意:这个全局过滤器一定要放在<span style="font-weight: 700;color: rgb(248, 57, 41);">OAuth2.0</span>鉴权过滤器之前,优先级要调高</p> <span style="float: right;display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">”</span> </blockquote> <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);">GrayRequestContextHolder</span>中,下面只需要改造Ribbon的负载均衡的策略去注册中心选择灰度服务。</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);">GrayRule</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/A7sq8BD8oexqmcDw0weKQeLicSXAich7jG16eyUm2W9VdeU7Z0qCf64Ymcsl1fpvAaWXhhAHibzYgw7ESqMqYpVVItwtialU7BnO/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #383a42;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fafafa;border-radius: 5px;"><span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/**<br>&nbsp;*&nbsp;灰度发布的规则<br>&nbsp;*/</span><br><span style="color: #a626a4;line-height: 26px;">public</span>&nbsp;<span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">class</span>&nbsp;<span style="color: #c18401;line-height: 26px;">GrayRule</span>&nbsp;<span style="color: #a626a4;line-height: 26px;">extends</span>&nbsp;<span style="color: #c18401;line-height: 26px;">ZoneAvoidanceRule</span>&nbsp;</span>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #4078f2;line-height: 26px;">@Override</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">public</span>&nbsp;<span style="color: #a626a4;line-height: 26px;">void</span>&nbsp;<span style="color: #4078f2;line-height: 26px;">initWithNiwsConfig</span><span style="line-height: 26px;">(IClientConfig&nbsp;clientConfig)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #4078f2;line-height: 26px;">@Override</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">public</span>&nbsp;Server&nbsp;<span style="color: #4078f2;line-height: 26px;">choose</span><span style="line-height: 26px;">(Object&nbsp;key)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">try</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//从ThreadLocal中获取灰度标记</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">boolean</span>&nbsp;grayTag&nbsp;=&nbsp;GrayRequestContextHolder.getGrayTag().get();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//获取所有可用服务</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;Server&gt;&nbsp;serverList&nbsp;=&nbsp;<span style="color: #a626a4;line-height: 26px;">this</span>.getLoadBalancer().getReachableServers();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//灰度发布的服务</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;Server&gt;&nbsp;grayServerList&nbsp;=&nbsp;<span style="color: #a626a4;line-height: 26px;">new</span>&nbsp;ArrayList&lt;&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//正常的服务</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;Server&gt;&nbsp;normalServerList&nbsp;=&nbsp;<span style="color: #a626a4;line-height: 26px;">new</span>&nbsp;ArrayList&lt;&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">for</span>(Server&nbsp;server&nbsp;:&nbsp;serverList)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NacosServer&nbsp;nacosServer&nbsp;=&nbsp;(NacosServer)&nbsp;server;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//从nacos中获取元素剧进行匹配</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">if</span>(nacosServer.getMetadata().containsKey(GrayConstant.GRAY_HEADER)<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;&amp;&amp;&nbsp;nacosServer.getMetadata().get(GrayConstant.GRAY_HEADER).equals(GrayConstant.GRAY_VALUE))&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;grayServerList.add(server);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #a626a4;line-height: 26px;">else</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;normalServerList.add(server);<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;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//如果被标记为灰度发布,则调用灰度发布的服务</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">if</span>(grayTag)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">return</span>&nbsp;originChoose(grayServerList,key);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #a626a4;line-height: 26px;">else</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">return</span>&nbsp;originChoose(normalServerList,key);<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: #a626a4;line-height: 26px;">finally</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//清除灰度标记</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GrayRequestContextHolder.remove();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">private</span>&nbsp;Server&nbsp;<span style="color: #4078f2;line-height: 26px;">originChoose</span><span style="line-height: 26px;">(List&lt;Server&gt;&nbsp;noMetaServerList,&nbsp;Object&nbsp;key)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Optional&lt;Server&gt;&nbsp;server&nbsp;=&nbsp;getPredicate().chooseRoundRobinAfterFiltering(noMetaServerList,&nbsp;key);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">if</span>&nbsp;(server.isPresent())&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">return</span>&nbsp;server.get();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #a626a4;line-height: 26px;">else</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">return</span>&nbsp;<span style="color: #a626a4;line-height: 26px;">null</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">逻辑很简单,如下:</p> <ol 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);"> 获取灰度标记 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 从Nacos注册中心获取灰度服务和正常服务 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 根据灰度标记去判断,如果灰度发布则选择特定的灰度服务进行转发 </section></li> </ol> <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);">GrayRule</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/A7sq8BD8oexqmcDw0weKQeLicSXAich7jG16eyUm2W9VdeU7Z0qCf64Ymcsl1fpvAaWXhhAHibzYgw7ESqMqYpVVItwtialU7BnO/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #383a42;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fafafa;border-radius: 5px;"><span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/**<br>&nbsp;*&nbsp;灰度部署的负载规则配置类<br>&nbsp;*&nbsp;注意:这个类一定不要被Spring Boot 扫描进入IOC容器中,一旦扫描进入则对全部的服务都将生效<br>&nbsp;*/</span><br><span style="color: #a626a4;line-height: 26px;">public</span>&nbsp;<span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">class</span>&nbsp;<span style="color: #c18401;line-height: 26px;">GrayRuleConfig</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #4078f2;line-height: 26px;">@Bean</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">public</span>&nbsp;GrayRule&nbsp;<span style="color: #4078f2;line-height: 26px;">grayRule</span><span style="line-height: 26px;">()</span></span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">return</span>&nbsp;<span style="color: #a626a4;line-height: 26px;">new</span>&nbsp;GrayRule();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br></code></pre> <blockquote data-tool="mdnice编辑器" style="border-width: initial;border-style: none;border-color: initial;font-size: 0.9em;overflow: auto;margin-bottom: 20px;margin-top: 20px;padding-top: 15px;padding-right: 10px;padding-bottom: 15px;line-height: 1.75;border-radius: 13px;color: rgb(53, 53, 53);background: rgb(245, 245, 245);"> <span style="display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;font-size: 16px;margin-right: 10px;margin-left: 10px;">注意:这个GrayRuleConfig不能被扫描进入IOC容器,一旦扫描进入则全局生效</p> <span style="float: right;display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">”</span> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">因为不仅仅网关需要用到这个灰度发布策略,凡是涉及到OpenFeign调用的微服务如果需要配置灰度发布都需要用到,因此这里陈某定义了一个公用的<span style="font-weight: 700;color: rgb(248, 57, 41);">gray-starter</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="color: rgb(255, 41, 65);"><strong>@RibbonClients</strong></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(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">openFeign透传灰度标记</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);">grayTag=true</span>)放在了请求头中,因此在下游服务中需要做的就只是从请求头中将灰度标记取出来,然后将其存入<span style="font-weight: 700;color: rgb(248, 57, 41);">GrayRequestContextHolder</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);">GrayRule</span>则能从<span style="font-weight: 700;color: rgb(248, 57, 41);">GrayRequestContextHolder</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);">问题来了:如何从请求头中取出灰度标记?</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;">在介绍OAuth2.0相关知识时,曾经出过一篇文章:<a href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247504759&amp;idx=1&amp;sn=e50d5b44eb64debf43c6d644f55c68b5&amp;chksm=fcf70cbacb8085aca5cd88688973ed45cd8bd9a4642ae97727f3684b431f80316e5c073d6946&amp;scene=21&amp;cur_album_id=2042874937312346114#wechat_redirect" style="color: rgb(248, 57, 41);border-bottom: 1px solid rgb(248, 57, 41);" data-linktype="2">实战!openFeign如何实现全链路JWT令牌信息不丢失?</a></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">其中介绍了令牌中继的解决方案,使用的是openFeign的请求拦截器去配置请求头信息。</p> <p style="text-align: center;margin-bottom: 0em;padding: 0px 0.5em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.26173541963015645" data-s="300,640" src="/upload/ba1d897e6f79647fb2943a0a2e81f759.png" data-type="png" data-w="703" style="box-shadow: rgb(210, 210, 210) 0em 0em 0.5em 0px;font-size: 17px;"></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;"></figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">如上图:openFeign在调用时并不是用的原先的Request,而是内部新建了一个Request,其中复制了请求的URL、请求参数一些信息,但是请求头并没有复制过去,因此openFeign调用会丢失请求头中的信息。</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);">RequestInterceptor</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/A7sq8BD8oexqmcDw0weKQeLicSXAich7jG16eyUm2W9VdeU7Z0qCf64Ymcsl1fpvAaWXhhAHibzYgw7ESqMqYpVVItwtialU7BnO/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #383a42;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fafafa;border-radius: 5px;"><span style="color: #4078f2;line-height: 26px;">@Component</span><br><span style="color: #4078f2;line-height: 26px;">@Slf</span>4j<br><span style="color: #a626a4;line-height: 26px;">public</span>&nbsp;<span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">class</span>&nbsp;<span style="color: #c18401;line-height: 26px;">FeignRequestInterceptor</span>&nbsp;<span style="color: #a626a4;line-height: 26px;">implements</span>&nbsp;<span style="color: #c18401;line-height: 26px;">RequestInterceptor</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #4078f2;line-height: 26px;">@Override</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">public</span>&nbsp;<span style="color: #a626a4;line-height: 26px;">void</span>&nbsp;<span style="color: #4078f2;line-height: 26px;">apply</span><span style="line-height: 26px;">(RequestTemplate&nbsp;template)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletRequest&nbsp;httpServletRequest&nbsp;=&nbsp;RequestContextUtils.getRequest();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map&lt;String,&nbsp;String&gt;&nbsp;headers&nbsp;=&nbsp;getHeaders(httpServletRequest);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">for</span>&nbsp;(Map.Entry&lt;String,&nbsp;String&gt;&nbsp;entry&nbsp;:&nbsp;headers.entrySet())&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//②&nbsp;设置请求头到新的Request中</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template.header(entry.getKey(),&nbsp;entry.getValue());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">/**<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;获取原请求头<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #a626a4;line-height: 26px;">private</span>&nbsp;Map&lt;String,&nbsp;String&gt;&nbsp;<span style="color: #4078f2;line-height: 26px;">getHeaders</span><span style="line-height: 26px;">(HttpServletRequest&nbsp;request)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map&lt;String,&nbsp;String&gt;&nbsp;map&nbsp;=&nbsp;<span style="color: #a626a4;line-height: 26px;">new</span>&nbsp;LinkedHashMap&lt;&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Enumeration&lt;String&gt;&nbsp;enumeration&nbsp;=&nbsp;request.getHeaderNames();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">if</span>&nbsp;(enumeration&nbsp;!=&nbsp;<span style="color: #a626a4;line-height: 26px;">null</span>)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">while</span>&nbsp;(enumeration.hasMoreElements())&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;key&nbsp;=&nbsp;enumeration.nextElement();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;value&nbsp;=&nbsp;request.getHeader(key);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//将灰度标记的请求头透传给下个服务</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a626a4;line-height: 26px;">if</span>&nbsp;(StrUtil.equals(GrayConstant.GRAY_HEADER,key)&amp;&amp;Boolean.TRUE.toString().equals(value)){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//①&nbsp;保存灰度发布的标记</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GrayRequestContextHolder.setGrayTag(<span style="color: #a626a4;line-height: 26px;">true</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.put(key,&nbsp;value);<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: #a626a4;line-height: 26px;">return</span>&nbsp;map;<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;"><span style="font-weight: 700;color: rgb(248, 57, 41);">①处的代码</span>:从请求头中获取灰度发布的标记,设置到<span style="font-weight: 700;color: rgb(248, 57, 41);">GrayRequestContextHolder</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);">②处的代码</span>:将这个请求头设置到新的Request中,继续向下游服务传递。</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);">RequestInterceptor</span>就已经完成了,关于灰度发布策略只需要复用网关的<span style="font-weight: 700;color: rgb(248, 57, 41);">GrayRule</span></p> <blockquote data-tool="mdnice编辑器" style="border-width: initial;border-style: none;border-color: initial;font-size: 0.9em;overflow: auto;margin-bottom: 20px;margin-top: 20px;padding-top: 15px;padding-right: 10px;padding-bottom: 15px;line-height: 1.75;border-radius: 13px;color: rgb(53, 53, 53);background: rgb(245, 245, 245);"> <span style="display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">“</span> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;font-size: 16px;margin-right: 10px;margin-left: 10px;">注意:也需要使用@RibbonClients注解去标注文章服务调用的哪些服务需要灰度发布。</p> <span style="float: right;display: block;font-size: 2em;color: rgb(248, 57, 41);font-family: Arial, serif;line-height: 1em;font-weight: 700;">”</span> </blockquote> <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/A7sq8BD8oexqmcDw0weKQeLicSXAich7jG16eyUm2W9VdeU7Z0qCf64Ymcsl1fpvAaWXhhAHibzYgw7ESqMqYpVVItwtialU7BnO/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #383a42;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fafafa;border-radius: 5px;"><span style="color: #4078f2;line-height: 26px;">@RibbonClients</span>(value&nbsp;=&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">//指定对comments这个服务开启灰度部署</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #4078f2;line-height: 26px;">@RibbonClient</span>(value&nbsp;=&nbsp;<span style="color: #50a14f;line-height: 26px;">"comments"</span>,configuration&nbsp;=&nbsp;GrayRuleConfig<span style="line-height: 26px;">.<span style="color: #a626a4;line-height: 26px;">class</span>)<br>})<br><span style="color: #c18401;line-height: 26px;">public</span>&nbsp;<span style="color: #c18401;line-height: 26px;">class</span>&nbsp;<span style="color: #c18401;line-height: 26px;">ArticleApplication</span>&nbsp;</span>{}<br></code></pre> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">Nacos中服务如何做灰度标记</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;">其实很简单,分为两种:</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="color: rgb(255, 41, 65);"><strong>1、在配置文件中指定,如下:</strong></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/A7sq8BD8oexqmcDw0weKQeLicSXAich7jG16eyUm2W9VdeU7Z0qCf64Ymcsl1fpvAaWXhhAHibzYgw7ESqMqYpVVItwtialU7BnO/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #383a42;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fafafa;border-radius: 5px;"><span style="color: #986801;line-height: 26px;">spring:</span><br>&nbsp;&nbsp;<span style="color: #986801;line-height: 26px;">cloud:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #986801;line-height: 26px;">nacos:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #986801;line-height: 26px;">discovery:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #986801;line-height: 26px;">metadata:</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #a0a1a7;font-style: italic;line-height: 26px;">##&nbsp;灰度标记</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #986801;line-height: 26px;">grayTag:</span>&nbsp;<span style="color: #0184bb;line-height: 26px;">true</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;"><strong><span style="color: rgb(255, 41, 65);">2、在Nacos中动态的指定灰度标记</span></strong></p> <p style="text-align: center;margin-bottom: 0em;padding: 0px 0.5em;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.8871715610510046" data-s="300,640" src="/upload/c95cfda38f9e75af97b89e3800ddeaae.png" data-type="png" data-w="647" style="box-shadow: rgb(210, 210, 210) 0em 0em 0.5em 0px;font-size: 17px;"></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;"></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);">grayTag=true</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(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">总结</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">微服务中全链路灰度发布方案其实很简单,重要的就是灰度打标,整体流程如下:</p> <ol 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);"> 网关中通过全局过滤器实现灰度打标,将灰度标记放入请求头中传递给下游服务 </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);"> 在openFeign调用时需要从请求头中获取灰度标记,放入上下文中 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> openFeign调用同样是根据自定义的负载均衡策略从注册中心获取灰度服务,进行调用 </section></li> </ol> </section>

SpringBoot+ElasticSearch 实现模糊查询,批量CRUD,排序,分页,高亮!

作者:微信小助手

<section data-mpa-template="t" mpa-from-tpl="t" data-mpa-powered-by="yiban.io"> <section data-mpa-template="t" mpa-from-tpl="t"> <section mpa-from-tpl="t"> <section mpa-from-tpl="t"> <section mpa-from-tpl="t"> <section mpa-from-tpl="t"> <h3 data-tool="mdnice编辑器" style="outline: 0px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(0, 0, 0);text-align: left;font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><em style="outline: 0px;max-width: 100%;color: rgb(136, 136, 136);font-size: 12px;letter-spacing: 0.5px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"></em></h3> <section style="margin-top: 1.4em;margin-bottom: 1.4em;outline: 0px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;font-size: medium;text-align: start;color: rgb(18, 18, 18);font-family: -apple-system, &quot;system-ui&quot;, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif;background-color: rgb(255, 255, 255);line-height: 2em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="outline: 0px;max-width: 100%;font-size: 16px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" data-mpa-powered-by="yiban.io" style="outline: 0px;max-width: 100%;color: rgb(34, 34, 34);font-family: system-ui, -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <h2 data-tool="mdnice编辑器" style="outline: 0px;font-weight: bold;font-size: 22px;max-width: 100%;letter-spacing: 0.544px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;border-bottom: 2px solid rgb(89, 89, 89);color: rgb(89, 89, 89);visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="outline: 0px;max-width: 100%;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">一、导入elasticsearch依赖</span></strong><span style="outline: 0px;max-width: 100%;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></h2> <section style="margin-top: 8px;margin-bottom: 16px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Segoe UI&quot;, Arial, freesans, sans-serif;font-size: 15px;text-size-adjust: inherit;line-height: 1.75em;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 在pom.xml里加入如下依赖 </section> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wJibWkqN1bUNUWLs6Ty7SWPOvTbzElXSrNW8NicYpsplemic3rfxZdnCPJfuvicvCEwTvcroWKh5ZhH5utQt0iaJ8fBXJdhss9ziao/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 677px;border-radius: 5px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">&lt;<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>&gt;</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">&lt;<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>&gt;</span>org.springframework.boot<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">&lt;/<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>&gt;</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">&lt;<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>&gt;</span>spring-boot-starter-data-elasticsearch<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">&lt;/<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>&gt;</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">&lt;/<span style="outline: 0px;max-width: 100%;color: rgb(224, 108, 117);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">dependency</span>&gt;</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <p data-tool="mdnice编辑器" style="margin-bottom: 16px;padding-top: 8px;padding-bottom: 8px;outline: 0px;max-width: 100%;font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Segoe UI&quot;, Arial, freesans, sans-serif;font-size: 15px;text-size-adjust: inherit;line-height: 1.75em;box-sizing: border-box !important;overflow-wrap: break-word !important;">非常重要:检查依赖版本是否与你当前所用的版本是否一致,如果不一致,会连接失败!</p> <p style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="rich_pages wxw-img" data-ratio="0.383008356545961" src="/upload/ae07db4e3b1b44f2337522aa1906b785.png" data-type="png" data-w="1436"></p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 30px;outline: 0px;font-weight: bold;font-size: 22px;max-width: 100%;letter-spacing: 0.544px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;border-bottom: 2px solid rgb(89, 89, 89);color: rgb(89, 89, 89);visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="outline: 0px;max-width: 100%;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">二、创建高级客户端</span></strong><span style="outline: 0px;max-width: 100%;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></h2> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wJibWkqN1bUNUWLs6Ty7SWPOvTbzElXSrNW8NicYpsplemic3rfxZdnCPJfuvicvCEwTvcroWKh5ZhH5utQt0iaJ8fBXJdhss9ziao/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 677px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.apache.http.HttpHost;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.elasticsearch.client.RestClient;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.elasticsearch.client.RestHighLevelClient;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.springframework.context.annotation.Bean;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.springframework.context.annotation.Configuration;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(97, 174, 238);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">@Configuration</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">public</span>&nbsp;<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">class</span>&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(230, 192, 123);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">ElasticSearchClientConfig</span>&nbsp;</span>{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(97, 174, 238);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">@Bean</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">public</span>&nbsp;RestHighLevelClient&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(97, 174, 238);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">restHighLevelClient</span><span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">()</span></span>{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RestHighLevelClient&nbsp;client&nbsp;=&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">new</span>&nbsp;RestHighLevelClient(<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RestClient.builder(<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&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="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">new</span>&nbsp;HttpHost(<span style="outline: 0px;max-width: 100%;color: rgb(152, 195, 121);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">"服务器IP"</span>,&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(209, 154, 102);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">9200</span>,&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(152, 195, 121);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">"http"</span>)));<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">return</span>&nbsp;client;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 30px;outline: 0px;font-weight: bold;font-size: 22px;max-width: 100%;letter-spacing: 0.544px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &quot;PingFang SC&quot;, Cambria, Cochin, Georgia, Times, &quot;Times New Roman&quot;, serif;text-align: left;border-bottom: 2px solid rgb(89, 89, 89);color: rgb(89, 89, 89);visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="outline: 0px;max-width: 100%;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;">三、基本用法</span></strong><span style="outline: 0px;max-width: 100%;display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></h2> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;outline: 0px;font-weight: bold;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">1.创建、判断存在、删除索引</h5> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;outline: 0px;max-width: 100%;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="margin-bottom: -7px;outline: 0px;max-width: 100%;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/wJibWkqN1bUNUWLs6Ty7SWPOvTbzElXSrNW8NicYpsplemic3rfxZdnCPJfuvicvCEwTvcroWKh5ZhH5utQt0iaJ8fBXJdhss9ziao/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 677px;border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><code style="padding: 15px 16px 16px;outline: 0px;max-width: 100%;overflow-x: auto;color: rgb(171, 178, 191);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(40, 44, 52);border-radius: 5px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.elasticsearch.action.support.master.AcknowledgedResponse;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.elasticsearch.client.RequestOptions;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.elasticsearch.client.RestHighLevelClient;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.elasticsearch.client.indices.CreateIndexRequest;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.elasticsearch.client.indices.CreateIndexResponse;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.elasticsearch.client.indices.GetIndexRequest;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.junit.jupiter.api.Test;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.springframework.beans.factory.annotation.Autowired;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;org.springframework.boot.test.context.SpringBootTest;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">import</span>&nbsp;java.io.IOException;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(97, 174, 238);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">@SpringBootTest</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">class</span>&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(230, 192, 123);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">ElasticsearchApplicationTests</span>&nbsp;</span>{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(97, 174, 238);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">@Autowired</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">private</span>&nbsp;RestHighLevelClient&nbsp;restHighLevelClient;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(97, 174, 238);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">@Test</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">void</span>&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(97, 174, 238);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">testCreateIndex</span><span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">()</span>&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">throws</span>&nbsp;IOException&nbsp;</span>{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//1.创建索引请求</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;CreateIndexRequest&nbsp;request&nbsp;=&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">new</span>&nbsp;CreateIndexRequest(<span style="outline: 0px;max-width: 100%;color: rgb(152, 195, 121);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">"ljx666"</span>);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//2.客户端执行请求IndicesClient,执行create方法创建索引,请求后获得响应</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;CreateIndexResponse&nbsp;response=<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;restHighLevelClient.indices().create(request,&nbsp;RequestOptions.DEFAULT);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;System.out.println(response);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(97, 174, 238);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">@Test</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">void</span>&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(97, 174, 238);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">testExistIndex</span><span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">()</span>&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">throws</span>&nbsp;IOException&nbsp;</span>{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//1.查询索引请求</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;GetIndexRequest&nbsp;request=<span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">new</span>&nbsp;GetIndexRequest(<span style="outline: 0px;max-width: 100%;color: rgb(152, 195, 121);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">"ljx666"</span>);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//2.执行exists方法判断是否存在</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">boolean</span>&nbsp;exists=restHighLevelClient.indices().exists(request,RequestOptions.DEFAULT);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;System.out.println(exists);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(97, 174, 238);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">@Test</span><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;<span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">void</span>&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(97, 174, 238);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">testDeleteIndex</span><span style="outline: 0px;max-width: 100%;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">()</span>&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(198, 120, 221);line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">throws</span>&nbsp;IOException&nbsp;</span>{<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="outline: 0px;max-width: 100%;color: rgb(92, 99, 112);font-style: italic;line-height: 26px;box-sizing: border-box !important;overflow-wrap: break-word !important;">//1.删除索引请求</span><br style="outline: 0px;max-widt

项目终于用上了插入式注解,真香!

作者:微信小助手

<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;">插入式注解处理器在《深入理解Java虚拟机》一书中有一些介绍(前端编译篇有提到),但一直没有机会使用,直到碰到这个需求,觉得再合适不过了,就简单用了一下,这里做个记录。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">了解过lombok底层原理的都知道其使用的就是的插入式注解,那么今天笔者就以真实场景演示一下插入式注解的使用。</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;">我们为公司提供了一套通用的JAVA基础组件包,组件包内有不同的模块,比如熔断模块、负载均模块、rpc模块等等,这些模块均会被打成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;">这份代码会不断的迭代,我们希望可以通过<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);">promethus</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.4033333333333333" data-type="png" data-w="600" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/5cfa308bc76e2b3068228a03c048f619.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;">我们希望看到每一个版本的使用率,这有利于我们做版本兼容,必要的时候可以对古早版本使用者溯源。</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;">需求似乎很简单,但真要获取自身的jar版本号还是挺麻烦的,有个比较简单但阴间的办法,就是给每一个组件都加上当前的jar版本号,写到配置文件里或者直接设置成常量,这样上报promethus时就可以直接获取到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;">有没有更好的解决办法呢?比如我们可不可以在gradle打包构建时拿到jar包的版本号,然后注入到每个组件中去呢?就像lombok那样,不需要写get、set方法,只需要加个注解标记就可以自动注入get、set方法。</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/A7sq8BD8oey2F0JZ6AzlEoBP1ibaVILiaFDakncpiacZJb8bPcD2fIROQiaKQ5q6G1Iibcy4tYolBAyDusmBTHk4ozCEJ7yFxuRvw/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;">@TrisceliVersion</span><br><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;">final</span>&nbsp;String&nbsp;version&nbsp;=&nbsp;<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;">然后像lombok生成set/get方法那样注入真正的版本号:</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/A7sq8BD8oey2F0JZ6AzlEoBP1ibaVILiaFDakncpiacZJb8bPcD2fIROQiaKQ5q6G1Iibcy4tYolBAyDusmBTHk4ozCEJ7yFxuRvw/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;">@TrisceliVersion</span><br><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;">final</span>&nbsp;String&nbsp;version&nbsp;=&nbsp;<span style="color: #c41a16;line-height: 26px;">"1.0.31-SNAPSHOT"</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;">参考lombok的实现,这其实是可以做到的,下面来看解决方案。</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;">java中解析一个注解的方式主要有两种:编译期扫描、运行期反射,这是lombok <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);">@Setter</code>的实现:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oey2F0JZ6AzlEoBP1ibaVILiaFDakncpiacZJb8bPcD2fIROQiaKQ5q6G1Iibcy4tYolBAyDusmBTHk4ozCEJ7yFxuRvw/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;">@Target</span>({ElementType.FIELD,&nbsp;ElementType.TYPE})<br><span style="color: #643820;line-height: 26px;">@Retention</span>(RetentionPolicy.SOURCE)<br><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="color: #643820;line-height: 26px;">@interface</span>&nbsp;Setter&nbsp;{<br>&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">//&nbsp;略...</span><br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">可以看到<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">@Setter</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);">Retention</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);">SOURCE</code>类型的,也就是说这个注解只在编译期有效,它甚至不会被编入class文件,所以lombok无疑是第一种解析方式,那用什么方式可以在编译期就让注解被解析到并执行我们的解析代码呢?答案就是定义插入式注解处理器(通过JSR-269提案定义的<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);">Pluggable Annotation Processing API</code>实现)</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">插入式注解处理器的触发点如下图所示:</p> <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.2557894736842105" data-type="png" data-w="950" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/16bd0e43e944491667533983b6f07b11.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;">也就是说插入式注解处理器可以帮助我们在编译期修改抽象语法树(AST)!所以现在我们只需要自定义一个这样的处理器,然后其内部拿到jar版本信息(因为是编译期,可以找到源码的path,源码里随便搞个文件存放版本号,然后用java io读取进来即可),再将注解对应语法树上的常量值设置成jar包版本号,语法树变了,最终生成的字节码也会跟着变,这样就实现了我们想在编译期给常量version注入值的愿望。</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/A7sq8BD8oey2F0JZ6AzlEoBP1ibaVILiaFDakncpiacZJb8bPcD2fIROQiaKQ5q6G1Iibcy4tYolBAyDusmBTHk4ozCEJ7yFxuRvw/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;">@Documented</span><br><span style="color: #643820;line-height: 26px;">@Retention</span>(RetentionPolicy.SOURCE)&nbsp;<span style="color: #007400;line-height: 26px;">//只在编译期有效,最终不会打进class文件中</span><br><span style="color: #643820;line-height: 26px;">@Target</span>({ElementType.FIELD})&nbsp;<span style="color: #007400;line-height: 26px;">//仅允许作用于类属性之上</span><br><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="color: #643820;line-height: 26px;">@interface</span>&nbsp;TrisceliVersion&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);">AbstractProcessor</code>的处理器:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oey2F0JZ6AzlEoBP1ibaVILiaFDakncpiacZJb8bPcD2fIROQiaKQ5q6G1Iibcy4tYolBAyDusmBTHk4ozCEJ7yFxuRvw/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: #007400;line-height: 26px;">/**<br>&nbsp;*&nbsp;{<span style="font-weight: bold;line-height: 26px;">@link</span>&nbsp;AbstractProcessor}&nbsp;就属于&nbsp;Pluggable&nbsp;Annotation&nbsp;Processing&nbsp;API<br>&nbsp;*/</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;">TrisceliVersionProcessor</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">extends</span>&nbsp;<span style="color: #5c2699;line-height: 26px;">AbstractProcessor</span>&nbsp;</span>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">private</span>&nbsp;JavacTrees&nbsp;javacTrees;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">private</span>&nbsp;TreeMaker&nbsp;treeMaker;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">private</span>&nbsp;ProcessingEnvironment&nbsp;processingEnv;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">/**<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;初始化处理器<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<span style="font-weight: bold;line-height: 26px;">@param</span>&nbsp;processingEnv&nbsp;提供了一系列的实用工具<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@SneakyThrows</span><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;<span style="color: #aa0d91;line-height: 26px;">synchronized</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">void</span>&nbsp;<span style="color: #1c00cf;line-height: 26px;">init</span><span style="color: #5c2699;line-height: 26px;">(ProcessingEnvironment&nbsp;processingEnv)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">super</span>.init(processingEnv);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">this</span>.processingEnv&nbsp;=&nbsp;processingEnv;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">this</span>.javacTrees&nbsp;=&nbsp;JavacTrees.instance(processingEnv);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Context&nbsp;context&nbsp;=&nbsp;((JavacProcessingEnvironment)&nbsp;processingEnv).getContext();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">this</span>.treeMaker&nbsp;=&nbsp;TreeMaker.instance(context);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br><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;SourceVersion&nbsp;<span style="color: #1c00cf;line-height: 26px;">getSupportedSourceVersion</span><span style="color: #5c2699;line-height: 26px;">()</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">return</span>&nbsp;SourceVersion.latest();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><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;Set&lt;String&gt;&nbsp;<span style="color: #1c00cf;line-height: 26px;">getSupportedAnnotationTypes</span><span style="color: #5c2699;line-height: 26px;">()</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HashSet&lt;String&gt;&nbsp;set&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;HashSet&lt;&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set.add(TrisceliVersion<span style="line-height: 26px;">.<span style="color: #aa0d91;line-height: 26px;">class</span>.<span style="color: #5c2699;line-height: 26px;">getName</span>())</span>;&nbsp;<span style="color: #007400;line-height: 26px;">//&nbsp;支持解析的注解</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">return</span>&nbsp;set;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><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;<span style="color: #aa0d91;line-height: 26px;">boolean</span>&nbsp;<span style="color: #1c00cf;line-height: 26px;">process</span><span style="color: #5c2699;line-height: 26px;">(Set&lt;?&nbsp;extends&nbsp;TypeElement&gt;&nbsp;annotations,&nbsp;RoundEnvironment&nbsp;roundEnv)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">for</span>&nbsp;(TypeElement&nbsp;t&nbsp;:&nbsp;annotations)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">for</span>&nbsp;(Element&nbsp;e&nbsp;:&nbsp;roundEnv.getElementsAnnotatedWith(t))&nbsp;{&nbsp;<span style="color: #007400;line-height: 26px;">//&nbsp;获取到给定注解的element(element可以是一个类、方法、包等)</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;">//&nbsp;JCVariableDecl为字段/变量定义语法树节点</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JCTree.JCVariableDecl&nbsp;jcv&nbsp;=&nbsp;(JCTree.JCVariableDecl)&nbsp;javacTrees.getTree(e);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;varType&nbsp;=&nbsp;jcv.vartype.type.toString();<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;(!<span style="color: #c41a16;line-height: 26px;">"java.lang.String"</span>.equals(varType))&nbsp;{&nbsp;<span style="color: #007400;line-height: 26px;">//&nbsp;限定变量类型必须是String类型,否则抛异常</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printErrorMessage(e,&nbsp;<span style="color: #c41a16;line-height: 26px;">"Type&nbsp;'"</span>&nbsp;+&nbsp;varType&nbsp;+&nbsp;<span style="color: #c41a16;line-height: 26px;">"'"</span>&nbsp;+&nbsp;<span style="color: #c41a16;line-height: 26px;">"&nbsp;is&nbsp;not&nbsp;support."</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;&nbsp;&nbsp;&nbsp;&nbsp;jcv.init&nbsp;=&nbsp;treeMaker.Literal(getVersion());&nbsp;<span style="color: #007400;line-height: 26px;">//&nbsp;给这个字段赋值,也就是getVersion的返回值</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;<span style="color: #aa0d91;line-height: 26px;">true</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">/**<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;利用processingEnv内的Messager对象输出一些日志<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<span style="font-weight: bold;line-height: 26px;">@param</span>&nbsp;e&nbsp;element<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<span style="font-weight: bold;line-height: 26px;">@param</span>&nbsp;m&nbsp;error&nbsp;message<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">private</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">void</span>&nbsp;<span style="color: #1c00cf;line-height: 26px;">printErrorMessage</span><span style="color: #5c2699;line-height: 26px;">(Element&nbsp;e,&nbsp;String&nbsp;m)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,&nbsp;m,&nbsp;e);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">private</span>&nbsp;String&nbsp;<span style="color: #1c00cf;line-height: 26px;">getVersion</span><span style="color: #5c2699;line-height: 26px;">()</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #007400;line-height: 26px;">/**<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;获取version,这里省略掉复杂的代码,直接返回固定值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</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;">"v1.0.1"</span>;<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;">定义好的处理器需要<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);">SPI机制</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);">META.services</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.6495726495726496" data-type="png" data-w="468" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/9ddd16f65cf14f48acd3c1e74d6d2cf0.png"> </figure> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(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;">新建测试模块,引入刚才写好的代码包:</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.1510204081632653" data-type="png" data-w="980" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/bf8e43dbc9e90d7894dc2ad316a71a9e.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;">这是Test类:</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.2175" data-type="png" data-w="800" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/77505eeea924b666869e25f70490e14a.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;">现在我们只需要让gradle build一下,新得到的字节码中该字段就有值了:</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.39125" data-type="png" data-w="800" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;height: auto !important;" src="/upload/21c7958233d72865fa8695230aeb4dc4.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;">这只是功能的冰山一角,既然它可以通过修改抽象语法树来控制生成的字节码,那么自然就有人能充分利用其特性来实现一些很酷的插件,比如lombok,我们再也不用写诸如set/get这种模板式的代码了,只要我们足够有创意,就可以让基于这一套API实现的插件在功能上有很大的发挥空间。</p> </section>

Redis实现微博好友功能微服务(关注,取关,共同关注)

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;overflow-wrap: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;margin-bottom: 0px;" data-mpa-powered-by="yiban.io"> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-

Spring Boot 接口数据加解密就该这样设计~

作者:微信小助手

<p style="margin: 10px 0px;padding: 0px;clear: both;min-height: 1em;max-width: 100%;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;orphans: 2;text-indent: 0px;text-transform: none;white-space: normal;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;outline: 0px;letter-spacing: 0.544px;color: rgb(62, 62, 62);font-size: 16px;text-align: left;widows: 1;word-spacing: 2px;background-color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;line-height: 2em;overflow-wrap: break-word !important;box-sizing: border-box !important;">今天这篇文章聊一聊接口安全问题,涉及到接口的加密、解密</p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;padding: 0 10px;word-spacing: 0px;word-break: break-word;word-wrap: break-word;text-align: left;line-height: 1.25;color: #2b2b2b;letter-spacing: 2px;background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.04) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(50, 0, 0, 0.04) 3%, rgba(0, 0, 0, 0) 3%);background-size: 20px 20px;background-position: center center;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: 26px;color: #2b2b2b;margin: 10px 0px;letter-spacing: 2px;font-size: 14px;word-spacing: 2px;"><img class="rich_pages wxw-img" data-ratio="0.6521197007481296" src="/upload/3a2c20c4a73b890608c5af78e360b48e.png" data-type="png" data-w="802" style="height: auto !important;"></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: #2b2b2b;margin: 10px 0px;letter-spacing: 2px;font-size: 14px;word-spacing: 2px;">和产品、前端同学对外需求后,梳理了相关技术方案, 主要的需求点如下:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;list-style-type: decimal;font-size: 15px;color: #595959;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-size: 14px;font-weight: normal;color: #595959;"> 尽量少改动,不影响之前的业务逻辑; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-size: 14px;font-weight: normal;color: #595959;"> 考虑到时间紧迫性,可采用对称性加密方式,服务需要对接安卓、IOS、H5三端,另外考虑到H5端存储密钥安全性相对来说会低一些,故分针对H5和安卓、IOS分配两套密钥; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-size: 14px;font-weight: normal;color: #595959;"> 要兼容低版本的接口,后面新开发的接口可不用兼容; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-size: 14px;font-weight: normal;color: #595959;"> 接口有GET和POST两种接口,需要都要进行加解密; </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: #2b2b2b;margin: 10px 0px;letter-spacing: 2px;font-size: 14px;word-spacing: 2px;">需求解析:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;list-style-type: decimal;font-size: 15px;color: #595959;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-size: 14px;font-weight: normal;color: #595959;"> 服务端、客户端和H5统一拦截加解密,网上有成熟方案,也可以按其他服务中实现的加解密流程来搞; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-size: 14px;font-weight: normal;color: #595959;"> 使用AES放松加密,考虑到H5端存储密钥安全性相对来说会低一些,故分针对H5和安卓、IOS分配两套密钥; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;text-align: left;font-size: 14px;font-weight: normal;color: #595959;"> 本次涉及客户端和服务端的整体改造,经讨论,新接口统一加 /secret/ 前缀来区分 </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: #2b2b2b;margin: 10px 0px;letter-spacing: 2px;font-size: 14px;word-spacing: 2px;">按本次需求来简单还原问题,定义两个对象,后面用得着,</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: #2b2b2b;margin: 10px 0px;letter-spacing: 2px;font-size: 14px;word-spacing: 2px;">用户类:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/et9q9FvjBBoKIEABtT5CAlrKRrvhYELoN9Bc8rqUicZT4XJMftn4o3OexUcQSibYAc0dXzObgYExOjsgMichW3MLScGmuM4icAYm/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;letter-spacing: 0px;padding-top: 15px;background: #282c34;border-radius: 5px;"><span style="color: #61aeee;line-height: 26px;">@Data</span><br><span style="color: #c678dd;line-height: 26px;">public</span>&nbsp;<span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;">class</span>&nbsp;<span style="color: #e6c07b;line-height: 26px;">User</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;Integer&nbsp;id;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;String&nbsp;name;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;UserType&nbsp;userType&nbsp;=&nbsp;UserType.COMMON;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #61aeee;line-height: 26px;">@JsonFormat</span>(pattern&nbsp;=&nbsp;<span style="color: #98c379;line-height: 26px;">"yyyy-MM-dd&nbsp;HH:mm:ss"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #c678dd;line-height: 26px;">private</span>&nbsp;LocalDateTime&nbsp;registerTime;<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: #2b2b2b;margin: 10px 0px;letter-spacing: 2px;font-size: 14px;word-spacing: 2px;">用户类型枚举类:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;backg

项目终于用上了动态Feign,真香!

作者:微信小助手

<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;"><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);">Feign</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);">编写Java Http</code>调用其他微服务的接口。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;">动态feign</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;">对于fegin调用,我们一般的用法:为每个<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);">微服务</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);">feignclient</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);">controller</code>接口,一一编写对应的方法,去调用对应微服务的接口。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">例如下面这样:</p> <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/A7sq8BD8oey2F0JZ6AzlEl7l8ekTxEoibmvE4mGkDrgibzmNBmQ50LeYweexaLP5tAbdwtFs64w1hcpibz4FUdK8g4T7hsxDXq2/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: #007400;line-height: 26px;">//system</span><br><span style="color: #643820;line-height: 26px;">@FeignClient</span>(name&nbsp;=&nbsp;<span style="color: #c41a16;line-height: 26px;">"system"</span>)<br><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;">SystemClient</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@GetMapping</span>(<span style="color: #c41a16;line-height: 26px;">"/system/test1"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">JsonResult&nbsp;<span style="color: #1c00cf;line-height: 26px;">test1</span><span style="color: #5c2699;line-height: 26px;">(String&nbsp;test1)</span></span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@GetMapping</span>(<span style="color: #c41a16;line-height: 26px;">"/system/test2"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">JsonResult&nbsp;<span style="color: #1c00cf;line-height: 26px;">test2</span><span style="color: #5c2699;line-height: 26px;">(String&nbsp;test2)</span></span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;....<br>}<br><br><span style="color: #007400;line-height: 26px;">//user</span><br><span style="color: #643820;line-height: 26px;">@FeignClient</span>(name&nbsp;=&nbsp;<span style="color: #c41a16;line-height: 26px;">"user"</span>)<br><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;">UserClient</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@GetMapping</span>(<span style="color: #c41a16;line-height: 26px;">"/user/test1"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">JsonResult&nbsp;<span style="color: #1c00cf;line-height: 26px;">test1</span><span style="color: #5c2699;line-height: 26px;">(String&nbsp;test1)</span></span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@GetMapping</span>(<span style="color: #c41a16;line-height: 26px;">"/user/test2"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">JsonResult&nbsp;<span style="color: #1c00cf;line-height: 26px;">test2</span><span style="color: #5c2699;line-height: 26px;">(String&nbsp;test2)</span></span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;<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;">这样写的话,可能会有些<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);">累赘</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);">动态的feign</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);">sytem微服务</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);">feignclient</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);">name</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);">system</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);">通用的方法</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);">url</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);">参数</code>,就可以了呢?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">答案是可以的!!!^_^</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">定义一个通用的接口,通用的get,post方法</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/A7sq8BD8oey2F0JZ6AzlEl7l8ekTxEoibmvE4mGkDrgibzmNBmQ50LeYweexaLP5tAbdwtFs64w1hcpibz4FUdK8g4T7hsxDXq2/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;">DynamicService</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@PostMapping</span>(<span style="color: #c41a16;line-height: 26px;">"{url}"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">Object&nbsp;<span style="color: #1c00cf;line-height: 26px;">executePostApi</span><span style="color: #5c2699;line-height: 26px;">(@PathVariable(<span style="color: #c41a16;line-height: 26px;">"url"</span>)</span>&nbsp;String&nbsp;url,&nbsp;@RequestBody&nbsp;Object&nbsp;params)</span>;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@GetMapping</span>(<span style="color: #c41a16;line-height: 26px;">"{url}"</span>)<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">Object&nbsp;<span style="color: #1c00cf;line-height: 26px;">executeGetApi</span><span style="color: #5c2699;line-height: 26px;">(@PathVariable(<span style="color: #c41a16;line-height: 26px;">"url"</span>)</span>&nbsp;String&nbsp;url,&nbsp;@SpringQueryMap&nbsp;Object&nbsp;params)</span>;<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">executePostApi:(post方法)</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);"> <p 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);">url</code>,表示你要调用微服务的接口url,一般来说是对应<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);">controller</code>接口的url;</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p 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);">params</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);">@RequestBody</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);">controller</code>接口,接收参数也需要加上该注解。</p> </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;">定义一个动态<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);">feignclient</code></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oey2F0JZ6AzlEl7l8ekTxEoibmvE4mGkDrgibzmNBmQ50LeYweexaLP5tAbdwtFs64w1hcpibz4FUdK8g4T7hsxDXq2/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;">DynamicClient</span>&nbsp;</span>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #643820;line-height: 26px;">@Autowired</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">private</span>&nbsp;DynamicFeignClientFactory&lt;DynamicService&gt;&nbsp;dynamicFeignClientFactory;<br><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;">executePostApi</span><span style="color: #5c2699;line-height: 26px;">(String&nbsp;feignName,&nbsp;String&nbsp;url,&nbsp;Object&nbsp;params)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DynamicService&nbsp;dynamicService&nbsp;=&nbsp;dynamicFeignClientFactory.getFeignClient(DynamicService<span style="line-height: 26px;">.<span style="color: #aa0d91;line-height: 26px;">class</span>,&nbsp;<span style="color: #5c2699;line-height: 26px;">feignName</span>)</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">return</span>&nbsp;dynamicService.executePostApi(url,&nbsp;params);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><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;">executeGetApi</span><span style="color: #5c2699;line-height: 26px;">(String&nbsp;feignName,&nbsp;String&nbsp;url,&nbsp;Object&nbsp;params)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DynamicService&nbsp;dynamicService&nbsp;=&nbsp;dynamicFeignClientFactory.getFeignClient(DynamicService<span style="line-height: 26px;">.<span style="color: #aa0d91;line-height: 26px;">class</span>,&nbsp;<span style="color: #5c2699;line-height: 26px;">feignName</span>)</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">return</span>&nbsp;dynamicService.executeGetApi(url,&nbsp;params);<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;">executePostApi:(post方法)</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);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">feignName,表示需要调用的微服务的名称,一般对应<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);">application.name</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);">system</code></p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p 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);">url</code>,表示你要调用微服务的接口url,一般来说是对应<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);">controller</code>接口的url;</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p 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);">params</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);">@RequestBody</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);">controller</code>接口,接收参数也需要加上该注解。</p> </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;">定义一个动态<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);">feignclient</code>工厂类</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/A7sq8BD8oey2F0JZ6AzlEl7l8ekTxEoibmvE4mGkDrgibzmNBmQ50LeYweexaLP5tAbdwtFs64w1hcpibz4FUdK8g4T7hsxDXq2/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;">DynamicFeignClientFactory</span>&lt;<span style="color: #5c2699;line-height: 26px;">T</span>&gt;&nbsp;</span>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">private</span>&nbsp;FeignClientBuilder&nbsp;feignClientBuilder;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;<span style="color: #1c00cf;line-height: 26px;">DynamicFeignClientFactory</span><span style="color: #5c2699;line-height: 26px;">(ApplicationContext&nbsp;appContext)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">this</span>.feignClientBuilder&nbsp;=&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;FeignClientBuilder(appContext);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: #aa0d91;line-height: 26px;">public</span>&nbsp;T&nbsp;<span style="color: #1c00cf;line-height: 26px;">getFeignClient</span><span style="color: #5c2699;line-height: 26px;">(<span style="color: #aa0d91;line-height: 26px;">final</span>&nbsp;Class&lt;T&gt;&nbsp;type,&nbsp;String&nbsp;serviceId)</span>&nbsp;</span>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #aa0d91;line-height: 26px;">return</span>&nbsp;<span style="color: #aa0d91;line-height: 26px;">this</span>.feignClientBuilder.forType(type,&nbsp;serviceId).build();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br></code></pre> <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;">主要的作用:是帮我们动态的创建一个<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);">feignclient</code>对象</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> <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/A7sq8BD8oey2F0JZ6AzlEl7l8ekTxEoibmvE4mGkDrgibzmNBmQ50LeYweexaLP5tAbdwtFs64w1hcpibz4FUdK8g4T7hsxDXq2/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;">DynamicClient&nbsp;dynamicClient&nbsp;=&nbsp;SpringUtil.getBean(DynamicClient<span style="line-height: 26px;">.<span style="color: #aa0d91;line-height: 26px;">class</span>)</span>;<br>Object&nbsp;result&nbsp;=&nbsp;dynamicClient.executePostApi(<span style="color: #c41a16;line-height: 26px;">"system"</span>,&nbsp;<span style="color: #c41a16;line-height: 26px;">"/system/test"</span>,&nbsp;<span style="color: #aa0d91;line-height: 26px;">new</span>&nbsp;HashMap&lt;&gt;());<br>System.out.println(<span style="color: #c41a16;line-height: 26px;">"==========&gt;"</span>+JSONObject.toJSONString(result));<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);">DynamicClient</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);">executePostApi</code>方法</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);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">"system",表示调用微服务的名称,一般对应<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);">application.name</code></p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">"/system/test",表示调用的<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);">url</code></p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">new HashMap&lt;&gt;(),为需要传递的参数</p> </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> </section>

面试官:说说什么是本地缓存、分布式缓存以及多级缓存,它们各自的优缺点

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding-right: 10px;padding-left: 10px;text-align: left;line-height: 1.6;letter-spacing: 0.034em;color: rgb(63, 63, 63);font-size: 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-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">像MySql等传统的关系型数据库已经不能适用于所有的业务场景,比如电商系统的秒杀场景,APP首页的访问流量高峰场景,很容易造成关系型数据库的瘫痪,随着缓存技术的出现很好的解决了这个问题。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;text-align: center;background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/0L82kuLBTiaoc5FoBKXth9vU5vuZjM3WnmPeyxQNmSWzbPHOfMaZ00XUMOZ7NUmRib7IMCicDeaCaCfG5IK2R7XZQ/640?wx_fmt=png&quot;);background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;margin-top: 1em;margin-bottom: 10px;"><span style="display: none;"></span><span style="display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;margin-top: 38px;font-size: 18px;margin-bottom: 10px;">一、缓存的概念(什么是缓存)</span></h2> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">缓存就是把访问量较高的热点数据从传统的关系型数据库中加载到内存中,当用户再次访问热点数据时是从内存中加载,减少了对数据库的访问量,解决了高并发场景下容易造成数据库宕机的问题。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;text-align: center;background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/0L82kuLBTiaoc5FoBKXth9vU5vuZjM3WnmPeyxQNmSWzbPHOfMaZ00XUMOZ7NUmRib7IMCicDeaCaCfG5IK2R7XZQ/640?wx_fmt=png&quot;);background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;margin-top: 1em;margin-bottom: 10px;"><span style="display: none;"></span><span style="display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;margin-top: 38px;font-size: 18px;margin-bottom: 10px;">二、为什么要用缓存(为什么要用redis作为缓存)</span></h2> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">针对于这个问题要从两个方面去考虑,一个是应用系统的高并发场景,另一个就是应用系统的高性能情况。</p> <h3 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;margin-top: 1.2em;"><span style="background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/0L82kuLBTiaoc5FoBKXth9vU5vuZjM3WnQZCsfFIgxCiaIKGZfZDYA5bQEnrVEJQlGK56Y5r0Hv1QYH0h01FJnicQ/640?wx_fmt=png&quot;);background-size: 100% 100%;background-repeat: no-repeat;display: inline-block;width: 16px;height: 15px;line-height: 15px;margin-bottom: -1px;"></span><span style="display: none;"></span><span style="font-size: 17px;display: inline-block;margin-left: 8px;color: rgb(72, 179, 120);">1、高性能情况</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">用户第一次访问数据时,缓存中没有数据,要从数据库中获取数据,因为是从磁盘中拿数据,读取数据的过程比较慢。拿到数据后将数据存储在缓存中,用户第二次访问数据时,可以从缓存中直接获取,因为缓存是直接操作内存的,访问数据速度比较快。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.8772635814889336" data-type="png" data-w="497" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;height: auto !important;" src="/upload/dbdd45855ec46f181f9cd428aa56bffb.png"> </figure> <h3 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;margin-top: 1.2em;"><span style="background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/0L82kuLBTiaoc5FoBKXth9vU5vuZjM3WnQZCsfFIgxCiaIKGZfZDYA5bQEnrVEJQlGK56Y5r0Hv1QYH0h01FJnicQ/640?wx_fmt=png&quot;);background-size: 100% 100%;background-repeat: no-repeat;display: inline-block;width: 16px;height: 15px;line-height: 15px;margin-bottom: -1px;"></span><span style="display: none;"></span><span style="font-size: 17px;display: inline-block;margin-left: 8px;color: rgb(72, 179, 120);">2、高并发场景下</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">操作缓存能够承受的并发访问量是远远大于访问数据库的,比如redis,它的读的速度是110000次/s,写的速度是81000次/s。所以说将数据库中访问量高的数据存储到缓存中,用户请求的时候直接访问数据库,不必访问数据库,提高应用程序的并发量。</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="1.0439276485788114" data-type="png" data-w="387" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;height: auto !important;" src="/upload/c61f7f40e067518d9c7f79df92ce44d7.png"> </figure> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;text-align: center;background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/0L82kuLBTiaoc5FoBKXth9vU5vuZjM3WnmPeyxQNmSWzbPHOfMaZ00XUMOZ7NUmRib7IMCicDeaCaCfG5IK2R7XZQ/640?wx_fmt=png&quot;);background-position: center center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 50px;margin-top: 1em;margin-bottom: 10px;"><span style="display: none;"></span><span style="display: inline-block;height: 38px;line-height: 42px;color: rgb(72, 179, 120);background-position: left center;background-repeat: no-repeat;background-attachment: initial;background-origin: initial;background-clip: initial;background-size: 63px;margin-top: 38px;font-size: 18px;margin-bottom: 10px;">三、缓存的分类有哪些</span></h2> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">缓存基本上分为三类:本地缓存、分布式缓存、多级缓存。根据缓存和应用程序是否属于同一个进程,将缓存分为本地缓存和分布式缓存。基于本地缓存和分布式缓存都有各自的优点和缺点,后面又出现了多级缓存的概念。</p> <h3 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;margin-top: 1.2em;"><span style="background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/0L82kuLBTiaoc5FoBKXth9vU5vuZjM3WnQZCsfFIgxCiaIKGZfZDYA5bQEnrVEJQlGK56Y5r0Hv1QYH0h01FJnicQ/640?wx_fmt=png&quot;);background-size: 100% 100%;background-repeat: no-repeat;display: inline-block;width: 16px;height: 15px;line-height: 15px;margin-bottom: -1px;"></span><span style="display: none;"></span><span style="font-size: 17px;display: inline-block;margin-left: 8px;color: rgb(72, 179, 120);">1、本地缓存</span><span style="display: none;"></span></h3> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;"><span style="display: none;"></span>本地缓存的概念:<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">本地缓存是指和应用程序在同一个进程内的内存空间去存储数据,数据的读写都是在同一个进程内完成的。</p> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;"><span style="display: none;"></span>本地缓存优点:<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">读取速度快,但是不能进行大数据量存储。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">本地缓存不需要远程网络请求去操作内存空间,没有额外的性能消耗,所以读取速度快。但是由于本地缓存占用了应用进程的内存空间,比如java进程的jvm内存空间,故不能进行大数据量存储。</p> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;"><span style="display: none;"></span>本地缓存缺点:<span style="display: none;"></span></h4> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="line-height: 1.75em;color: rgb(74, 74, 74);">应用程序集群部署时,会存在数据更新问题(数据更新不一致)</strong> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">本地缓存一般只能被同一个应用进程的程序访问,不能被其他应用程序进程访问。在单体应用集群部署时,如果数据库有数据需要更新,就要同步更新不同服务器节点上的本地缓存的数据来保证数据的一致性,但是这种操作的复杂度高,容易出错。可以基于redis的发布/订阅机制来实现各个部署节点的数据同步更新。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="line-height: 1.75em;color: rgb(74, 74, 74);">数据会随着应用程序的重启而丢失</strong> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">因为本地缓存的数据是存储在应用进程的内存空间的,所以当应用进程重启时,本地缓存的数据会丢失。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">本地缓存的实现</strong>:</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">(1)、缓存存储的数据一般都是key-value键值对的数据结构,在java语言中,常用的字典实现包括 HashMap 和 ConcurretHashMap。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">(2)、除了上面说的实现方式以外,也可以用Guava、Ehcache以及Caffeine等封装好的工具包来实现本地缓存。</p> <h3 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;margin-top: 1.2em;"><span style="background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/0L82kuLBTiaoc5FoBKXth9vU5vuZjM3WnQZCsfFIgxCiaIKGZfZDYA5bQEnrVEJQlGK56Y5r0Hv1QYH0h01FJnicQ/640?wx_fmt=png&quot;);background-size: 100% 100%;background-repeat: no-repeat;display: inline-block;width: 16px;height: 15px;line-height: 15px;margin-bottom: -1px;"></span><span style="display: none;"></span><span style="font-size: 17px;display: inline-block;margin-left: 8px;color: rgb(72, 179, 120);">2、分布式缓存</span><span style="display: none;"></span></h3> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;"><span style="display: none;"></span>分布式缓存概念:<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">分布式缓存是独立部署的服务进程,并且和应用程序没有部署在同一台服务器上。所以是需要通过远程网络请求来完成分布式缓存的读写操作,并且分布式缓存主要应用在应用程序集群部署的环境下。</p> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;"><span style="display: none;"></span>分布式缓存优点:<span style="display: none;"></span></h4> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="line-height: 1.75em;color: rgb(74, 74, 74);">支持大数据量存储</strong> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">分布式缓存是独立部署的进程,拥有自身独自的内存空间,不需要占用应用程序进程的内存空间,并且还支持横向扩展的集群方式部署,所以可以进行大数据量存储。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="line-height: 1.75em;color: rgb(74, 74, 74);">数据不会随着应用程序重启而丢失</strong> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">分布式缓存和本地缓存不同,拥有自身独立的内存空间,不会受到应用程序进程重启的影响,在应用程序重启时,分布式缓存的存储数据仍然存在。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="line-height: 1.75em;color: rgb(74, 74, 74);">数据集中存储,保证数据的一致性</strong> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">当应用程序采用集群方式部署时,集群的每个部署节点都有一个统一的分布式缓存进行数据的读写操作,所以不会存在像本地缓存中数据更新问题,保证了不同服务器节点的 数据一致性。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="line-height: 1.75em;color: rgb(74, 74, 74);">数据读写分离,高性能,高可用</strong>分布式缓存一般支持数据副本机制,实现读写分离,可以解决高并发场景中的数据读写性能问题。而且在多个缓存节点冗余存储数据,提高了缓存数据的可用性,避免某个缓存节点宕机导致数据不可用问题。 </section></li> </ul> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;"><span style="display: none;"></span>分布式缓存缺点:<span style="display: none;"></span></h4> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: black;" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="line-height: 1.75em;color: rgb(74, 74, 74);">数据跨网络传输,读写性能不如本地缓存</strong> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">分布式缓存是一个独立的服务进程,并且和应用程序进程不在同一台机器上,所以数据的读写要通过远程网络请求,这样相对于本地缓存的数据读写,性能要低一些。</p> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 18px;margin-top: 30px;"><span style="display: none;"></span>分布式缓存的实现:<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">分布式缓存的典型实现包括 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">MemCached 和 Redis</code>。</p> <h3 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;margin-top: 1.2em;"><span style="background-image: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/0L82kuLBTiaoc5FoBKXth9vU5vuZjM3WnQZCsfFIgxCiaIKGZfZDYA5bQEnrVEJQlGK56Y5r0Hv1QYH0h01FJnicQ/640?wx_fmt=png&quot;);background-size: 100% 100%;background-repeat: no-repeat;display: inline-block;width: 16px;height: 15px;line-height: 15px;margin-bottom: -1px;"></span><span style="display: none;"></span><span style="font-size: 17px;display: inline-block;margin-left: 8px;color: rgb(72, 179, 120);">3、多级缓存</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">基于本地缓存和分布式缓存的优缺点,多级缓存应运而生,在实际的业务开发中一般也是采用多级缓存。</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;background: rgb(251, 249, 253);color: rgb(106, 115, 125);margin-bottom: 20px;margin-top: 20px;padding: 15px 20px;line-height: 27px;border-left-color: rgb(53, 179, 120);"> <p style="line-height: 26px;font-size: 15px;color: rgb(89, 89, 89);">注意:本地缓存一般存储更新频率低,访问频率高数据,分布式缓存一般存储更新频率很高的数据。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;"><strong style="line-height: 1.75em;">多级缓存的请求流程</strong>:本地缓存作为一级缓存,分布式缓存作为二级缓存;当用户获取数据时,先从一级缓存中获取数据,如果一级缓存有数据则返回数据,否则从二级缓存中获取数据。如果二级缓存中有数据则更新一级缓存,然后将数据返回客户端。如果二级缓存没有数据则去数据库查询数据,然后更新二级缓存,接着再更新一级缓存,最后将数据返回给客户端。</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.8674911660777385" data-type="png" data-w="566" style="display: block;margin-right: auto;margin-left: auto;border-radius: 4px;margin-bottom: 25px;height: auto !important;" src="/upload/ff5f96e2097900d76382034668aa5500.png"> </figure> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">多级缓存的实现:可以使用<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">Guava</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(40, 202, 113);">Caffeine</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(40, 202, 113);">Redis</code>作为二级缓存。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;">注意:在应用程序集群部署时,如果数据库的数据有更新的情况,一级缓存的数据更新容易出现数据不一致的情况。因为是集群部署,多个部署节点实现一级缓存数据更新难度比较大,不过我们可以通过<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(40, 202, 113);">Redis</code>的消息发布/订阅机制来实现多个节点缓存数据一致性问题。</p> <p data-tool="mdnice编辑器" style="padding-bottom: 8px;padding-top: 1em;color: rgb(74, 74, 74);line-height: 1.75em;text-align: right;"><span style="font-size: 11px;color: rgb(214, 214, 214);">来源:<span style="color: rgb(214, 214, 214);font-size: 11px;font-family: -apple-system-font, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei UI&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;letter-spacing: 0.544px;text-align: start;widows: 1;word-spacing: 2px;caret-color: rgb(51, 51, 51);background-color: rgb(255, 255, 255);">blog.csdn.net/you18131371836/article/details/118212987</span></span></p> </section>

数据大屏最简单自适应方案,无需适配 rem 单位

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-bottom: 0px;padding-right: 10px;padding-left: 10px;letter-spacing: 0px;white-space: normal;font-size: 16px;color: black;line-height: 1.6;word-break: break-word;overflow-wrap: 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;"> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="font-size: 18px;color: rgb(61, 167, 66);">前言</span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">您是不是有如下疑惑。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">开发数据大屏不能完全自适应?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">使用rem自适应还需要注意单位很麻烦?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">有没有那种随便我怎么写都能够完全自适应的?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">有没有那种用最少的代码最简单的方法实现完全自适应?最好是不需要我用脑子去思考的那种方法。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>有</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">使用scale适配大屏。实现数据大屏在任何分辨率的电脑上均可安然运作。无需特定编写rem单位,也不需要考虑单位使用失误导致适配不完全。您即使全部用position去定位在其他屏幕上都不会乱。(%和px随便用)</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">最终效果👇</p> <p style="text-align: center;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.514176245210728" data-s="300,640" src="/upload/c465b51defd555dc93f2793d25cf34d5.png" data-type="gif" data-w="1305"></p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="font-size: 18px;color: rgb(61, 167, 66);">如果您是一位React玩家</span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">那一切都简单了,您只需要复制就好。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.4499593165174939" src="/upload/b920078eef50878eea0005754adfb5c3.jpg" data-type="other" data-w="1229" style="margin-right: auto;margin-left: auto;display: block;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">代码👇</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/UDa9R1yl9Uaarn4SIO6Ej6QWrx7WxxkjChko3b8wH6J5JRR8ia6w6NTX8FuZicPet9jwRdcjZn8MG5SLnCKiaOX7HCwKRKCZAnF/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 557.778px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;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;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">/*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JS部分<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//数据大屏自适应函数</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;handleScreenAuto&nbsp;=&nbsp;<span style="line-height: 26px;"><span style="line-height: 26px;">()</span>&nbsp;=&gt;</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;designDraftWidth&nbsp;=&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">1920</span>;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//设计稿的宽度</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;designDraftHeight&nbsp;=&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">960</span>;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//设计稿的高度</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//根据屏幕的变化适配的比例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;scale&nbsp;=&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientWidth&nbsp;/&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientHeight&nbsp;&lt;&nbsp;designDraftWidth&nbsp;/&nbsp;designDraftHeight&nbsp;?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientWidth&nbsp;/&nbsp;designDraftWidth)&nbsp;:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientHeight&nbsp;/&nbsp;designDraftHeight);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//缩放比例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.querySelector(<span style="color: rgb(152, 195, 121);line-height: 26px;">'#screen'</span>)&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">as</span>&nbsp;any).style.transform&nbsp;=&nbsp;<span style="color: rgb(152, 195, 121);line-height: 26px;">`scale(<span style="color: rgb(224, 108, 117);line-height: 26px;">${scale}</span>)&nbsp;translate(-50%)`</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//React的生命周期&nbsp;如果你是vue可以放到mountd或created中</span><br>&nbsp;&nbsp;&nbsp;&nbsp;useEffect(<span style="line-height: 26px;"><span style="line-height: 26px;">()</span>&nbsp;=&gt;</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//初始化自适应&nbsp;&nbsp;----在刚显示的时候就开始适配一次</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handleScreenAuto();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//绑定自适应函数&nbsp;&nbsp;&nbsp;---防止浏览器栏变化后不再适配</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">window</span>.onresize&nbsp;=&nbsp;<span style="line-height: 26px;"><span style="line-height: 26px;">()</span>&nbsp;=&gt;</span>&nbsp;handleScreenAuto();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//退出大屏后自适应消失&nbsp;&nbsp;&nbsp;---这是react的组件销毁生命周期,如果你是vue则写在deleted中。最好在退出大屏的时候接触自适应</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">return</span>&nbsp;<span style="line-height: 26px;"><span style="line-height: 26px;">()</span>&nbsp;=&gt;</span>&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">window</span>.onresize&nbsp;=&nbsp;<span style="color: rgb(86, 182, 194);line-height: 26px;">null</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;[])<br>&nbsp;&nbsp;&nbsp;&nbsp;<br><br></code></pre> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/UDa9R1yl9Uaarn4SIO6Ej6QWrx7WxxkjChko3b8wH6J5JRR8ia6w6NTX8FuZicPet9jwRdcjZn8MG5SLnCKiaOX7HCwKRKCZAnF/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 557.778px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;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;">&nbsp;&nbsp;&nbsp;&nbsp;/*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HTML部分<br>&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;div&nbsp;className=<span style="color: rgb(152, 195, 121);line-height: 26px;">"screen-wrapper"</span>&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div&nbsp;className=<span style="color: rgb(152, 195, 121);line-height: 26px;">"screen"</span>&nbsp;id=<span style="color: rgb(152, 195, 121);line-height: 26px;">"screen"</span>&gt;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br></code></pre> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/UDa9R1yl9Uaarn4SIO6Ej6QWrx7WxxkjChko3b8wH6J5JRR8ia6w6NTX8FuZicPet9jwRdcjZn8MG5SLnCKiaOX7HCwKRKCZAnF/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 557.778px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;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;">&nbsp;&nbsp;&nbsp;&nbsp;/*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CSS部分&nbsp;&nbsp;--除了设计稿的宽高是根据您自己的设计稿决定以外,其他复制粘贴就完事<br>&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;<br>&nbsp;&nbsp;.screen-root&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;height:&nbsp;100%;<br>&nbsp;&nbsp;&nbsp;&nbsp;width:&nbsp;100%;<br>&nbsp;&nbsp;&nbsp;&nbsp;.screen&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;display:&nbsp;inline-block;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width:&nbsp;1920px;&nbsp;&nbsp;//设计稿的宽度<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height:&nbsp;960px;&nbsp;&nbsp;//设计稿的高度<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;transform-origin:&nbsp;0&nbsp;0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;position:&nbsp;absolute;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;left:&nbsp;50%;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>}<br><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>将上面JS部分的代码复制到大屏的页面中,然后在id为screen中绘制大屏,即可完成效果。</strong></p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="font-size: 18px;color: rgb(61, 167, 66);">如果您是一位Vue玩家</span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">也不必担心,因为我也准备Vue版本的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">代码↓</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/UDa9R1yl9Uaarn4SIO6Ej6QWrx7WxxkjChko3b8wH6J5JRR8ia6w6NTX8FuZicPet9jwRdcjZn8MG5SLnCKiaOX7HCwKRKCZAnF/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 557.778px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;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;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">/**<br>&nbsp;&nbsp;&nbsp;&nbsp;js部分<br>&nbsp;&nbsp;&nbsp;&nbsp;*/</span><br>&nbsp;&nbsp;&nbsp;&nbsp;mounted(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//初始化自适应&nbsp;&nbsp;----在刚显示的时候就开始适配一次</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handleScreenAuto();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//绑定自适应函数&nbsp;&nbsp;&nbsp;---防止浏览器栏变化后不再适配</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">window</span>.onresize&nbsp;=&nbsp;<span style="line-height: 26px;"><span style="line-height: 26px;">()</span>&nbsp;=&gt;</span>&nbsp;handleScreenAuto();<br>&nbsp;&nbsp;&nbsp;&nbsp;},<br>&nbsp;&nbsp;&nbsp;&nbsp;deleted(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">window</span>.onresize&nbsp;=&nbsp;<span style="color: rgb(86, 182, 194);line-height: 26px;">null</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;},<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">methods</span>:&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//数据大屏自适应函数</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;handleScreenAuto&nbsp;=&nbsp;():&nbsp;<span style="line-height: 26px;"><span style="line-height: 26px;">void</span>&nbsp;=&gt;</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;designDraftWidth&nbsp;=&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">1920</span>;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//设计稿的宽度</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;designDraftHeight&nbsp;=&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">960</span>;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//设计稿的高度</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//根据屏幕的变化适配的比例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;scale&nbsp;=&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientWidth&nbsp;/&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientHeight&nbsp;&lt;&nbsp;designDraftWidth&nbsp;/&nbsp;designDraftHeight&nbsp;?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientWidth&nbsp;/&nbsp;designDraftWidth)&nbsp;:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientHeight&nbsp;/&nbsp;designDraftHeight);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//缩放比例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.querySelector(<span style="color: rgb(152, 195, 121);line-height: 26px;">'#screen'</span>)&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">as</span>&nbsp;any).style.transform&nbsp;=&nbsp;<span style="color: rgb(152, 195, 121);line-height: 26px;">`scale(<span style="color: rgb(224, 108, 117);line-height: 26px;">${scale}</span>)&nbsp;translate(-50%)`</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br></code></pre> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/UDa9R1yl9Uaarn4SIO6Ej6QWrx7WxxkjChko3b8wH6J5JRR8ia6w6NTX8FuZicPet9jwRdcjZn8MG5SLnCKiaOX7HCwKRKCZAnF/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 557.778px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;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;">/**<br>&nbsp;&nbsp;&nbsp;&nbsp;html部分<br>&nbsp;*/<br>&nbsp;&lt;template&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div&nbsp;className=<span style="color: rgb(152, 195, 121);line-height: 26px;">"screen-wrapper"</span>&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div&nbsp;className=<span style="color: rgb(152, 195, 121);line-height: 26px;">"screen"</span>&nbsp;id=<span style="color: rgb(152, 195, 121);line-height: 26px;">"screen"</span>&gt;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br>&nbsp;&lt;/template&gt;<br></code></pre> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/UDa9R1yl9Uaarn4SIO6Ej6QWrx7WxxkjChko3b8wH6J5JRR8ia6w6NTX8FuZicPet9jwRdcjZn8MG5SLnCKiaOX7HCwKRKCZAnF/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 557.778px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;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;">&nbsp;&nbsp;&nbsp;&nbsp;/*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CSS部分&nbsp;&nbsp;--除了设计稿的宽高是根据您自己的设计稿决定以外,其他复制粘贴就完事<br>&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&lt;style&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.screen-root&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;height:&nbsp;100%;<br>&nbsp;&nbsp;&nbsp;&nbsp;width:&nbsp;100%;<br>&nbsp;&nbsp;&nbsp;&nbsp;.screen&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;display:&nbsp;inline-block;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width:&nbsp;1920px;&nbsp;&nbsp;//设计稿的宽度<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height:&nbsp;960px;&nbsp;&nbsp;//设计稿的高度<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;transform-origin:&nbsp;0&nbsp;0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;position:&nbsp;absolute;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;left:&nbsp;50%;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&lt;style&gt;<br><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">同样。将上述生命周期和methods中的代码复制,然后在id为screen的div中编写数据大屏即可。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="font-size: 18px;color: rgb(61, 167, 66);">如果您想了解实现原理</span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">用是会用了。有人问这个方法的实现原理咋办?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">找不到人讲解这个方法为什么可以实现自适应咋办?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>没关系,我来提供答案</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">问题是:为什么,使用以上方法可以实现自适应。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">上代码,先从 handleScreenAuto 开始。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/UDa9R1yl9Uaarn4SIO6Ej6QWrx7WxxkjChko3b8wH6J5JRR8ia6w6NTX8FuZicPet9jwRdcjZn8MG5SLnCKiaOX7HCwKRKCZAnF/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 557.778px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;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;">&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;handleScreenAuto&nbsp;=&nbsp;<span style="line-height: 26px;"><span style="line-height: 26px;">()</span>&nbsp;=&gt;</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;designDraftWidth&nbsp;=&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">1920</span>;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//设计稿的宽度</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;designDraftHeight&nbsp;=&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">960</span>;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//设计稿的高度</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//根据屏幕的变化适配的比例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;scale&nbsp;=&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientWidth&nbsp;/&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientHeight&nbsp;&lt;&nbsp;designDraftWidth&nbsp;/&nbsp;designDraftHeight&nbsp;?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientWidth&nbsp;/&nbsp;designDraftWidth)&nbsp;:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientHeight&nbsp;/&nbsp;designDraftHeight);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//缩放比例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.querySelector(<span style="color: rgb(152, 195, 121);line-height: 26px;">'#screen'</span>)&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">as</span>&nbsp;any).style.transform&nbsp;=&nbsp;<span style="color: rgb(152, 195, 121);line-height: 26px;">`scale(<span style="color: rgb(224, 108, 117);line-height: 26px;">${scale}</span>)&nbsp;translate(-50%)`</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>designDraftWidth&nbsp;</strong>/<strong>&nbsp;designDraftHeight</strong>;这两个属性,叫做:设计稿宽高。顾名思义:就是设计师给我们出的那个设计稿是按照什么宽高比例出的设计图。换言之,我们制作视图的时候,得有个固定的宽高值。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">比如我用的蓝湖。就有标注,设计师给出的设计稿是按照什么宽高比例绘制的图形。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="2.0320855614973263" src="/upload/1c6d657a5e12689f0b3d00087e57d58.jpg" data-type="other" data-w="374" style="margin-right: auto;margin-left: auto;display: block;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">现在假设宽为1920高为960的情况下,我开始绘制大屏。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">下面就需要解释&nbsp;<strong>scale&nbsp;</strong>属性是干啥的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">scale英文直译:比例。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>对,这个属性就是决定,当我当前的屏幕大小和设计稿大小不符合的时候。我需要进行缩放的比例是多少。</strong></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">举个例子。如果我们的自己屏幕大小是1920 * 960,全用px(像素单位) 去绘制。那么当我们的大屏出现在1440 * 900的屏幕上的时候,我们的大屏,就无法完全的展示。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">比如:我把自适应效果去掉。我们看看结果(以下是在1440*900且无自适应的情况下的大屏,显然,它没有完全显示)</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.6001348617666892" src="/upload/b2b0475d55246628e912ada0a4ab7d5.jpg" data-type="other" data-w="1483" style="margin-right: auto;margin-left: auto;display: block;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">其实很简单,1440 * 900的像素无法显示1920*960的所有像素。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">既然1440 * 900 的情况下无法显示1920 * 960 的像素,那么缩放它,不就可以显示了吗?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">如何计算缩放比例,这就是scale的用处了。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/UDa9R1yl9Uaarn4SIO6Ej6QWrx7WxxkjChko3b8wH6J5JRR8ia6w6NTX8FuZicPet9jwRdcjZn8MG5SLnCKiaOX7HCwKRKCZAnF/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 557.778px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;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;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;scale&nbsp;=&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientWidth&nbsp;/&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientHeight&nbsp;&lt;&nbsp;designDraftWidth&nbsp;/&nbsp;designDraftHeight&nbsp;?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientWidth&nbsp;/&nbsp;designDraftWidth)&nbsp;:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientHeight&nbsp;/&nbsp;designDraftHeight);<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">不难看懂。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">scale就是拿出&nbsp;<strong>当前的电脑屏幕宽度像素(1440)除以当前屏幕高度像素(900)</strong>&nbsp;去和我们的设计稿宽度像素(1920)除以设计稿高度(960)做一个比较。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">如果当前屏幕比例&lt;设计稿比例。那么我们需要缩放的比例就是屏幕宽度除以设计稿宽度</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">如果当前屏幕比例&gt;设计稿比例。那么我们需要缩放的比例就是屏幕高度除以设计稿高度</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">那么 1440/900 = 1.6 。1920/960 = 2</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">因为1.6 &lt; 2。(当前屏幕比例小于设计稿比例)</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">所以我们需要缩放的比例是:屏幕宽度除以设计稿宽度 = 1440/1920 = 0.75。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">回到刚才的问题,1920 * 960 的像素无法在1440 * 900像素中完全显示的原因是 1440 * 900无法完全展示超过自身的像素点。那么,我们只需要<strong>将当前视图整体✖我们刚刚算出来的缩放比例</strong>(0.75)。就可以让1440 * 900的屏幕去容纳我们的大屏了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">1920 * 0.75 === 1440;960 * 0.75 = 720。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">经过缩放以后,原本1920 * 960 的大屏就可以在1440 * 900中展示。</p> <blockquote data-tool="mdnice编辑器" style="margin-top: 20px;margin-bottom: 20px;padding: 10px 10px 10px 20px;border-left-color: rgb(255, 218, 169);color: rgb(106, 115, 125);font-size: 0.9em;border-top: none;border-right: none;border-bottom: none;overflow: auto;background: rgba(0, 0, 0, 0.05);"> <p style="padding-top: 8px;padding-bottom: 8px;color: black;line-height: 26px;font-size: 15px;">值得注意的是,在退出大屏的时候,最好执行一下&nbsp;<strong><em>window.onresize = null</em></strong>。因为这种自适应主要是为数据大屏准备的。它并不适所有场景。如果是项目的其他内容需要自适应(比如表格表单页)。我更建议您使用栅格化系统。</p> </blockquote> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;"><span style="font-size: 18px;color: rgb(61, 167, 66);">您是否需要一个完整的demo?</span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>demo效果</strong></p> <p style="text-align: center;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.5145425700687467" data-s="300,640" src="/upload/26994f8fff934056399589ab8627525f.png" data-type="gif" data-w="1891"></p> <p style="text-align: center;"><br></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>html &nbsp;---- react/vue通用</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="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/UDa9R1yl9Uaarn4SIO6Ej6QWrx7WxxkjChko3b8wH6J5JRR8ia6w6NTX8FuZicPet9jwRdcjZn8MG5SLnCKiaOX7HCwKRKCZAnF/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 557.778px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;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="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">/*<br>html<br>*/</span><br><br>&nbsp;&lt;div&nbsp;className=<span style="color: rgb(152, 195, 121);line-height: 26px;">"screen-wrapper"</span>&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="line-height: 26px;">&lt;<span style="color: rgb(224, 108, 117);line-height: 26px;">div</span>&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">className</span>=<span style="color: rgb(152, 195, 121);line-height: 26px;">"screen"</span>&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">id</span>=<span style="color: rgb(152, 195, 121);line-height: 26px;">"screen"</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: rgb(224, 108, 117);line-height: 26px;">div</span>&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">className</span>=<span style="color: rgb(152, 195, 121);line-height: 26px;">"demo-root"</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: rgb(224, 108, 117);line-height: 26px;">header</span>&gt;</span>头部<span style="line-height: 26px;">&lt;/<span style="color: rgb(224, 108, 117);line-height: 26px;">header</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: rgb(224, 108, 117);line-height: 26px;">main</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&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: rgb(224, 108, 117);line-height: 26px;">div</span>&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">className</span>=<span style="color: rgb(152, 195, 121);line-height: 26px;">"demo-left"</span>&gt;</span><span style="line-height: 26px;">&lt;/<span style="color: rgb(224, 108, 117);line-height: 26px;">div</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&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: rgb(224, 108, 117);line-height: 26px;">div</span>&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">className</span>=<span style="color: rgb(152, 195, 121);line-height: 26px;">"demo-center"</span>&gt;</span><span style="line-height: 26px;">&lt;/<span style="color: rgb(224, 108, 117);line-height: 26px;">div</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&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: rgb(224, 108, 117);line-height: 26px;">div</span>&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">className</span>=<span style="color: rgb(152, 195, 121);line-height: 26px;">"demo-right"</span>&gt;</span><span style="line-height: 26px;">&lt;/<span style="color: rgb(224, 108, 117);line-height: 26px;">div</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: rgb(224, 108, 117);line-height: 26px;">main</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: rgb(224, 108, 117);line-height: 26px;">footer</span>&gt;</span>底部<span style="line-height: 26px;">&lt;/<span style="color: rgb(224, 108, 117);line-height: 26px;">footer</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: rgb(224, 108, 117);line-height: 26px;">div</span>&gt;</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;">&lt;/<span style="color: rgb(224, 108, 117);line-height: 26px;">div</span>&gt;</span></span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: 26px;"><span style="line-height: 26px;">&lt;<span style="color: rgb(224, 108, 117);line-height: 26px;">footer</span>&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">className</span>=<span style="color: rgb(152, 195, 121);line-height: 26px;">"large-footer"</span>&gt;</span><span style="line-height: 26px;">&lt;/<span style="color: rgb(224, 108, 117);line-height: 26px;">footer</span>&gt;</span></span><br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;<span style="color: rgb(152, 195, 121);line-height: 26px;">/div&gt;<br></span></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>css部分 ---react/vue通用</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="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/UDa9R1yl9Uaarn4SIO6Ej6QWrx7WxxkjChko3b8wH6J5JRR8ia6w6NTX8FuZicPet9jwRdcjZn8MG5SLnCKiaOX7HCwKRKCZAnF/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 557.778px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;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="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">/*<br>css<br>*/</span><br>.screen-wrapper&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">height</span>:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">100</span>%;<br>&nbsp;&nbsp;&nbsp;&nbsp;width:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">100</span>%;<br>&nbsp;&nbsp;&nbsp;&nbsp;.screen&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">display</span>:&nbsp;inline-block;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">1920</span>px;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">960</span>px;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;transform-origin:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">0</span>&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">0</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;position:&nbsp;absolute;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;left:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">50</span>%;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.demo-root{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;header{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">width</span>:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">1920</span>px;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">200</span>px;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;background:&nbsp;rgba(<span style="color: rgb(209, 154, 102);line-height: 26px;">53</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">150</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">206</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">0.3</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font-size:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">40</span>px;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text-align:&nbsp;center;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line-height:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">200</span>px;<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;main{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">display</span>:&nbsp;flex;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">660</span>px;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;div{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">width</span>:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">640</span>px;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">100</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;&nbsp;&nbsp;&nbsp;&nbsp;.demo-left{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">background</span>:&nbsp;rgba(<span style="color: rgb(209, 154, 102);line-height: 26px;">206</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">52</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">154</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">0.3</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;&nbsp;&nbsp;&nbsp;&nbsp;.demo-center{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">background</span>:&nbsp;rgba(<span style="color: rgb(209, 154, 102);line-height: 26px;">13</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">30</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">179</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">0.3</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;&nbsp;&nbsp;&nbsp;&nbsp;.demo-right{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">background</span>:&nbsp;rgba(<span style="color: rgb(209, 154, 102);line-height: 26px;">64</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">163</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">6</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">0.849</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;&nbsp;&nbsp;&nbsp;&nbsp;footer{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">width</span>:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">100</span>%;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">100</span>px;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font-size:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">40</span>px;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text-align:&nbsp;center;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line-height:&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">100</span>px;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;background:&nbsp;rgba(<span style="color: rgb(209, 154, 102);line-height: 26px;">19</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">211</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">115</span>,&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">0.3</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;}<br>}<br><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>js部分 ---react</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="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/UDa9R1yl9Uaarn4SIO6Ej6QWrx7WxxkjChko3b8wH6J5JRR8ia6w6NTX8FuZicPet9jwRdcjZn8MG5SLnCKiaOX7HCwKRKCZAnF/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 557.778px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;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;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">/*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;js&nbsp;&nbsp;---react<br>&nbsp;&nbsp;&nbsp;&nbsp;*/</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//数据大屏自适应函数</span><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;handleScreenAuto&nbsp;=&nbsp;():&nbsp;<span style="line-height: 26px;"><span style="line-height: 26px;">void</span>&nbsp;=&gt;</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;designDraftWidth&nbsp;=&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">1920</span>;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//设计稿的宽度</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;designDraftHeight&nbsp;=&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">960</span>;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//设计稿的高度</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//根据屏幕的变化适配的比例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;scale&nbsp;=&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientWidth&nbsp;/&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientHeight&nbsp;&lt;&nbsp;designDraftWidth&nbsp;/&nbsp;designDraftHeight&nbsp;?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientWidth&nbsp;/&nbsp;designDraftWidth)&nbsp;:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientHeight&nbsp;/&nbsp;designDraftHeight);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//缩放比例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.querySelector(<span style="color: rgb(152, 195, 121);line-height: 26px;">'#screen'</span>)&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">as</span>&nbsp;any).style.transform&nbsp;=&nbsp;<span style="color: rgb(152, 195, 121);line-height: 26px;">`scale(<span style="color: rgb(224, 108, 117);line-height: 26px;">${scale}</span>)&nbsp;translate(-50%)`</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//React的生命周期&nbsp;如果你是vue可以放到mountd或created中</span><br>&nbsp;&nbsp;&nbsp;&nbsp;useEffect(<span style="line-height: 26px;"><span style="line-height: 26px;">()</span>&nbsp;=&gt;</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//初始化自适应&nbsp;&nbsp;----在刚显示的时候就开始适配一次</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handleScreenAuto();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//绑定自适应函数&nbsp;&nbsp;&nbsp;---防止浏览器栏变化后不再适配</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">window</span>.onresize&nbsp;=&nbsp;<span style="line-height: 26px;"><span style="line-height: 26px;">()</span>&nbsp;=&gt;</span>&nbsp;handleScreenAuto();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//退出大屏后自适应消失&nbsp;&nbsp;&nbsp;---这是react的组件销毁生命周期,如果你是vue则写在deleted中。最好在退出大屏的时候接触自适应</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">return</span>&nbsp;<span style="line-height: 26px;"><span style="line-height: 26px;">()</span>&nbsp;=&gt;</span>&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">window</span>.onresize&nbsp;=&nbsp;<span style="color: rgb(86, 182, 194);line-height: 26px;">null</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;[])<br>&nbsp;&nbsp;&nbsp;&nbsp;<br><br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>js部分 ---vue</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="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_svg/UDa9R1yl9Uaarn4SIO6Ej6QWrx7WxxkjChko3b8wH6J5JRR8ia6w6NTX8FuZicPet9jwRdcjZn8MG5SLnCKiaOX7HCwKRKCZAnF/640?wx_fmt=svg&quot;) 10px 10px / 40px no-repeat rgb(40, 44, 52);height: 30px;width: 557.778px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;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;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">/*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;js&nbsp;&nbsp;---vue<br>&nbsp;&nbsp;&nbsp;&nbsp;*/</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mounted(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//初始化自适应&nbsp;&nbsp;----在刚显示的时候就开始适配一次</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;handleScreenAuto();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//绑定自适应函数&nbsp;&nbsp;&nbsp;---防止浏览器栏变化后不再适配</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">window</span>.onresize&nbsp;=&nbsp;<span style="line-height: 26px;"><span style="line-height: 26px;">()</span>&nbsp;=&gt;</span>&nbsp;handleScreenAuto();<br>&nbsp;&nbsp;&nbsp;&nbsp;},<br>&nbsp;&nbsp;&nbsp;&nbsp;deleted(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">window</span>.onresize&nbsp;=&nbsp;<span style="color: rgb(86, 182, 194);line-height: 26px;">null</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;},<br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">methods</span>:&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//数据大屏自适应函数</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;handleScreenAuto&nbsp;=&nbsp;():&nbsp;<span style="line-height: 26px;"><span style="line-height: 26px;">void</span>&nbsp;=&gt;</span>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;designDraftWidth&nbsp;=&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">1920</span>;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//设计稿的宽度</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;designDraftHeight&nbsp;=&nbsp;<span style="color: rgb(209, 154, 102);line-height: 26px;">960</span>;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//设计稿的高度</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//根据屏幕的变化适配的比例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">const</span>&nbsp;scale&nbsp;=&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientWidth&nbsp;/&nbsp;<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientHeight&nbsp;&lt;&nbsp;designDraftWidth&nbsp;/&nbsp;designDraftHeight&nbsp;?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientWidth&nbsp;/&nbsp;designDraftWidth)&nbsp;:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.documentElement.clientHeight&nbsp;/&nbsp;designDraftHeight);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(92, 99, 112);font-style: italic;line-height: 26px;">//缩放比例</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style="color: rgb(230, 192, 123);line-height: 26px;">document</span>.querySelector(<span style="color: rgb(152, 195, 121);line-height: 26px;">'#screen'</span>)&nbsp;<span style="color: rgb(198, 120, 221);line-height: 26px;">as</span>&nbsp;any).style.transform&nbsp;=&nbsp;<span style="color: rgb(152, 195, 121);line-height: 26px;">`scale(<span style="color: rgb(224, 108, 117);line-height: 26px;">${scale}</span>)&nbsp;translate(-50%)`</span>;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br></code></pre> <section style="margin-top: 24px;padding-top: 8px;padding-bottom: 8px;line-height: 26px;"> <span style="color: rgb(61, 167, 66);font-size: 18px;font-weight: bold;letter-spacing: 0px;"></span> <span style="color: rgb(61, 167, 66);font-size: 18px;font-weight: bold;letter-spacing: 0px;">追加,您是否担心,这其中会不会有什么坑?</span> </section> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">我可以很负责任的告诉您:<strong>有</strong>;</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">主要存在两个问题</p> <ol data-tool="mdnice编辑器" class="list-paddingleft-1" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;width: 557.205px;"> <li style="font-weight: bold;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong>当缩放比例过大时候,字体会有一点点模糊,就一点点。</strong> </section></li> <li style="font-weight: bold;"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong>当缩放比例过大时候,事件热区会偏移。</strong> </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">请不要太担心,第一个问题他只有在缩放真的很极端情况下才会出现那种让人难以接受的模糊。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="1.1107205623901582" src="/upload/bbf05cd715ac472c1a5ea390a3ea728f.jpg" data-type="other" data-w="569" style="margin-right: auto;margin-left: auto;display: block;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">一般情况下,在画圈这部分的分辨率下都是没什么大问题的。如果是公司内部使用的大屏,对UI真的没有苛刻到一定的程度,这个方法放心大胆用,没有关系的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">第二个问题,他的出现条件甚至比第一个问题还极端一点。仅仅从日常使用的角度来说,是没问题的。emmmmm...至少到现在为止还没有客户和我反应过这个问题。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">毕竟现在市场上几乎没有1280的显示器了。所以,不要太担心。</p> </section>

公司的这种打包启动方式,我简直惊呆了!

作者:微信小助手

<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;padding: 5px;font-size: 16px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, &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;">大家都知道,SpringBoot应用最终会打出一个<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);">Fat Jar</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);">java -jar xxx.jar</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;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247520168&amp;idx=1&amp;sn=89732de3c6b9faa4d9af312f6bd93d4f&amp;chksm=fcf75065cb80d973234c7af37c768c2f2760c411cfec480d189b26a4ad8f8036b814e00c1330&amp;token=1444528013&amp;lang=zh_CN&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1"><span class="js_jump_icon h5_image_link" data-positionback="static" style="inset: auto;margin: 20px 0px;"><img class="rich_pages wxw-img" data-ratio="0.475" src="/upload/61afb0f15d17901199efe58592dffc1c.jpg" data-w="640" style="border-radius: 6px;display: block;margin: 0px;max-width: 95%;object-fit: contain;"></span></a> </figure> <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);">loader.path</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);">java -Dloader.path=libs -jar xxxx</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;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247520168&amp;idx=1&amp;sn=89732de3c6b9faa4d9af312f6bd93d4f&amp;chksm=fcf75065cb80d973234c7af37c768c2f2760c411cfec480d189b26a4ad8f8036b814e00c1330&amp;token=1444528013&amp;lang=zh_CN&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1"><span class="js_jump_icon h5_image_link" data-positionback="static" style="inset: auto;margin: 20px 0px;"><img class="rich_pages wxw-img" data-ratio="0.6316410861865407" src="/upload/577ef3015cf3c58cd5f53b6d2a27c09f.png" data-type="png" data-w="847" style="border-radius: 6px;display: block;margin: 0px;max-width: 95%;object-fit: contain;"></span></a> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这样做最大的一个好处就是如果发现某个依赖出现问题,那么我只需要在libs替换其中某个依赖,影响范围可以减小很多。</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> <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;">主要是通过两个maven插件打出这样的结构的包。</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;"><span style="color: rgb(248, 57, 41);">1. spring-boot-maven-plugin</span></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;">该插件是<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);">spring boot</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);">fat jar</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);">java -jar xxx.jar</code>方式启动。官网地址:https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/。</p> <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> <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;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247520168&amp;idx=1&amp;sn=89732de3c6b9faa4d9af312f6bd93d4f&amp;chksm=fcf75065cb80d973234c7af37c768c2f2760c411cfec480d189b26a4ad8f8036b814e00c1330&amp;token=1444528013&amp;lang=zh_CN&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1"><span class="js_jump_icon h5_image_link" data-positionback="static" style="inset: auto;margin: 20px 0px;"><img class="rich_pages wxw-img" data-ratio="0.7770448548812665" src="/upload/2c5619d39aa2ad3e30988c6582378ccb.png" data-type="png" data-w="758" style="border-radius: 6px;display: block;margin: 0px;max-width: 95%;object-fit: contain;"></span></a> </figure> <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);"> <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);">layout</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);">ZIP</code>,后面说明原因。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <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);">includes</code>: 选择包含哪些依赖,这里写了一个不存在的jar,那么也间接实现了不打入其他的依赖。这种方式比较ugly,但是目前没有找到更加合适的方案。关注公众号:码猿技术专栏,回复关键词:1111 获取阿里内部的java性能调优手册 </section></li> </ul> <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;"><span style="color: rgb(248, 57, 41);">2. maven-assembly-plugin</span></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;">maven-assembly-plugin插件可以灵活定制打包内容,官网地址:https://maven.apache.org/plugins/maven-assembly-plugin/。</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;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247520168&amp;idx=1&amp;sn=89732de3c6b9faa4d9af312f6bd93d4f&amp;chksm=fcf75065cb80d973234c7af37c768c2f2760c411cfec480d189b26a4ad8f8036b814e00c1330&amp;token=1444528013&amp;lang=zh_CN&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1"><span class="js_jump_icon h5_image_link" data-positionback="static" style="inset: auto;margin: 20px 0px;"><img class="rich_pages wxw-img" data-ratio="0.6137142857142858" src="/upload/5c19bb6aa06df55c11dc704ab9631923.png" data-type="png" data-w="875" style="border-radius: 6px;display: block;margin: 0px;max-width: 95%;object-fit: contain;"></span></a> </figure> <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);">assembly.xml</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;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247520168&amp;idx=1&amp;sn=89732de3c6b9faa4d9af312f6bd93d4f&amp;chksm=fcf75065cb80d973234c7af37c768c2f2760c411cfec480d189b26a4ad8f8036b814e00c1330&amp;token=1444528013&amp;lang=zh_CN&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1"><span class="js_jump_icon h5_image_link" data-positionback="static" style="inset: auto;margin: 20px 0px;"><img class="rich_pages wxw-img" data-ratio="0.6813186813186813" src="/upload/91db8beb6324b698c6e2e3a45c9bc026.png" data-type="png" data-w="910" style="border-radius: 6px;display: block;margin: 0px;max-width: 95%;object-fit: contain;"></span></a> </figure> <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);">include</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);">exclude</code>属性通过正则灵活的抽取相关依赖到指定的目录下</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">最终执行<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">mvn clean package</code>在target目录下得到最终的安装包:</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;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247520168&amp;idx=1&amp;sn=89732de3c6b9faa4d9af312f6bd93d4f&amp;chksm=fcf75065cb80d973234c7af37c768c2f2760c411cfec480d189b26a4ad8f8036b814e00c1330&amp;token=1444528013&amp;lang=zh_CN&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1"><span class="js_jump_icon h5_image_link" data-positionback="static" style="inset: auto;margin: 20px 0px;"><img class="rich_pages wxw-img" data-ratio="0.06643356643356643" src="/upload/5a136ed626d2b5713b1b1d47ff8827bd.png" data-w="286" style="border-radius: 6px;display: block;margin: 0px;max-width: 95%;object-fit: contain;"></span></a> </figure> <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;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247520168&amp;idx=1&amp;sn=89732de3c6b9faa4d9af312f6bd93d4f&amp;chksm=fcf75065cb80d973234c7af37c768c2f2760c411cfec480d189b26a4ad8f8036b814e00c1330&amp;token=1444528013&amp;lang=zh_CN&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1"><span class="js_jump_icon h5_image_link" data-positionback="static" style="inset: auto;margin: 20px 0px;"><img class="rich_pages wxw-img" data-ratio="0.21842105263157896" src="/upload/fed005bb68c2da4e60e71619ce6452a1.png" data-type="png" data-w="760" style="border-radius: 6px;display: block;margin: 0px;max-width: 95%;object-fit: contain;"></span></a> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">打开libs目录:</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;"> <a target="_blank" href="https://mp.weixin.qq.com/s?__biz=MzU3MDAzNDg1MA==&amp;mid=2247520168&amp;idx=1&amp;sn=89732de3c6b9faa4d9af312f6bd93d4f&amp;chksm=fcf75065cb80d973234c7af37c768c2f2760c411cfec480d189b26a4ad8f8036b814e00c1330&amp;token=1444528013&amp;lang=zh_CN&amp;scene=21#wechat_redirect" textvalue="你已选中了添加链接的内容" linktype="text" imgurl="" imgdata="null" tab="innerlink" data-linktype="1"><span class="js_jump_icon h5_image_link" data-positionback="static" style="inset: auto;margin: 20px 0px;"><img class="rich_pages wxw-img" data-ratio="0.2435723951285521" src="/upload/d9be97f7cacfe5ceea67e0417999d202.png" data-type="png" data-w="739" style="border-radius: 6px;display: block;margin: 0px;max-width: 95%;object-fit: contain;"></span></a> </figure> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(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;">现在我们已经按照自己想要的结构打出包了,那如何在启动的时候加载<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);">libs</code>目录中的依赖呢?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">前面提到了<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">springboot</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);">springboot</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);">org.springframework.boot.loader.Launcher</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);">Spring Boot</code> 可执行 jar 的主要入口点;<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;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;">关</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;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;">注公众号:</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;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;">码猿技术专栏,回复关键词:</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;letter-spacing: 0.8px;text-align: left;word-spacing: 0.8px;">1111 获取阿里内部的java性能调优手册;</span>它是 <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);">Spring Boot jar</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);">Main-Class</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);">URLClassLoader</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);">Spring Boot</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);">main()</code>方法。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">Launcher</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);">JarLauncher</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);">WarLauncher</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);">PropertiesLauncher</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);">layout</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);">ZIP</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);">PropertiesLauncher</code>。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">PropertiesLauncher机制说明:</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;">默认情况下,<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);">PropertiesLauncher</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);">BOOT-INF/lib/</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);">loader.properties</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);">loader.path</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);">LOADER_PATH</code> 环境变量来增加其它的加载位置。</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);"> <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);">loader.path</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);">Classpath</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);">lib,${HOME}/app/lib</code>,前面的路径优先,类似于 javac 命令中的 <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);">-classpath</code>。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <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);">loader.home</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);">loader.path</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);">${user.dir}</code>。 </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;">所以,打包成功后,我们可以通过<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);">java -jar -Dloader.path=xx1,xx2,public &lt;jarName&gt;.jar</code> 命令来启动程序,这样对应目录下的依赖均会被加载。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(234, 84, 41);letter-spacing: 0.5444px;padding-bottom: 10px;border-bottom: 2px solid rgb(234, 84, 41);visibility: visible;">总结</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这种打包启动方式虽然不常见,但是还是有一定的价值的,特别是在项目组件模块比较多的时候,出现紧急缺陷,可以按需替换包,将影响范围控制到最小。</p> </section>