<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://shenyu.apache.org/zh/blog</id>
    <title>Apache ShenYu Blog</title>
    <updated>2026-01-23T10:37:48.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://shenyu.apache.org/zh/blog"/>
    <subtitle>Apache ShenYu Blog</subtitle>
    <icon>https://shenyu.apache.org/zh/img/favicon.svg</icon>
    <entry>
        <title type="html"><![CDATA[Apollo数据同步源码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Apollo-Data-Sync</id>
        <link href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Apollo-Data-Sync"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[本文基于shenyu-2.6.1版本进行源码分析，官网的介绍请参考 数据同步原理 。]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p>本文基于<code>shenyu-2.6.1</code>版本进行源码分析，官网的介绍请参考 <a href="https://shenyu.apache.org/zh/docs/design/data-sync" target="_blank" rel="noopener noreferrer" class="">数据同步原理</a> 。</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="admin管理端">Admin管理端<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Apollo-Data-Sync#admin%E7%AE%A1%E7%90%86%E7%AB%AF" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>以新增插件的流程来理解下整体的流程</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/Apollo-Sync-b0720ba3b1fe0dfcb554b104a78ce2bd.png" width="1051" height="561" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="接收数据">接收数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Apollo-Data-Sync#%E6%8E%A5%E6%94%B6%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<ul>
<li class="">PluginController.createPlugin()</li>
</ul>
<p>进入<code>PluginController</code>类中的<code>createPlugin()</code>方法，它负责数据的校验，添加或更新数据，返回结果信息。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Validated</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequiredArgsConstructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RestController</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequestMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/plugin"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">PluginController</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@PostMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@RequiresPermissions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"system:plugin:add"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuAdminResult</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@Valid</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@ModelAttribute</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginDTO</span><span class="token plain"> pluginDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 调用pluginService.createOrUpdate 进行处理逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuAdminResult</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">success</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createOrUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="处理数据">处理数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Apollo-Data-Sync#%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<ul>
<li class="">PluginServiceImpl.createOrUpdate() -&gt; PluginServiceImpl.create()</li>
</ul>
<p>在<code>PluginServiceImpl</code>类中通过<code>create()</code>方法完成数据的转换，保存到数据库，发布事件。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@RequiredArgsConstructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">PluginServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SelectorService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 事件发布对象 pluginEventPublisher</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginEventPublisher</span><span class="token plain"> pluginEventPublisher</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginDTO</span><span class="token plain"> pluginDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 判断有没有对应的插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">Assert</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nameExisted</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">AdminConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN_NAME_IS_EXIST</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 自定义的插件jar</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getFile</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Assert</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isTrue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">checkFile</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Base64</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">decode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getFile</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">AdminConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">THE_PLUGIN_JAR_FILE_IS_NOT_CORRECT_OR_EXCEEDS_16_MB</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 创建plugin对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">PluginDO</span><span class="token plain"> pluginDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">PluginDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildPluginDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 插入对象到数据库</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 插件新增成功，则发布创建事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// publish create event. init plugin data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        pluginEventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onCreated</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CREATE_SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>在<code>PluginServiceImpl</code>类完成数据的持久化操作，即保存数据到数据库，并通过 <code>pluginEventPublisher</code> 进行发布事件。</p>
<p><code>pluginEventPublisher.onCreateed</code>方法的逻辑是：发布变更的事件。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onCreated</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginDO</span><span class="token plain"> plugin</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发布DataChangeEvent事件：事件分组(插件、选择器、规则)、事件类型(创建、删除、更新)、变更的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CREATE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PluginTransfer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">mapToData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plugin</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发布PluginCreatedEvent</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">publish</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">PluginCreatedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plugin</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">SessionUtil</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">visitorName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>发布变更数据通过<code>publisher.publishEvent()</code>完成，这个<code>publisher</code>对象是一个<code>ApplicationEventPublisher</code>类，这个类的全限定名是<code>org.springframework.context.ApplicationEventPublisher</code>。看到这儿，我们知道了发布数据是通过<code>Spring</code>相关的功能来完成的。</p>
<blockquote>
<p>关于<code>ApplicationEventPublisher</code>：</p>
<p>当有状态发生变化时，发布者调用 <code>ApplicationEventPublisher</code> 的 <code>publishEvent</code> 方法发布一个事件，<code>Spring</code>容器广播事件给所有观察者，调用观察者的 <code>onApplicationEvent</code> 方法把事件对象传递给观察者。调用 <code>publishEvent</code>方法有两种途径，一种是实现接口由容器注入 <code>ApplicationEventPublisher</code> 对象然后调用其方法，另一种是直接调用容器的方法，两种方法发布事件没有太大区别。</p>
<ul>
<li class=""><code>ApplicationEventPublisher</code>：发布事件；</li>
<li class=""><code>ApplicationEvent</code>：<code>Spring</code> 事件，记录事件源、时间和数据；</li>
<li class=""><code>ApplicationListener</code>：事件监听者，观察者；</li>
</ul>
</blockquote>
<p>在<code>Spring</code>的事件发布机制中，有三个对象，</p>
<p>一个是发布事件的<code>ApplicationEventPublisher</code>，在<code>ShenYu</code>中通过构造器注入了一个<code>eventPublisher</code>。</p>
<p>另一个对象是<code>ApplicationEvent</code>，在<code>ShenYu</code>中通过<code>DataChangedEvent</code>继承了它，表示事件对象。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">ApplicationEvent</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>最后一个是 <code>ApplicationListener</code>，在<code>ShenYu</code>中通过<code>DataChangedEventDispatcher</code>类实现了该接口，作为事件的监听者，负责处理事件对象。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEventDispatcher</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataChangedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="分发数据">分发数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Apollo-Data-Sync#%E5%88%86%E5%8F%91%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<ul>
<li class="">DataChangedEventDispatcher.onApplicationEvent()</li>
</ul>
<p>当事件发布完成后，会自动进入到<code>DataChangedEventDispatcher</code>类中的<code>onApplicationEvent()</code>方法，进行事件处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEventDispatcher</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataChangedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 有数据变更时，调用此方法</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param event</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"unchecked"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历数据变更监听器（这里只会注册ApolloDataChangedListener）</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataChangedListener</span><span class="token plain"> listener </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> listeners</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 依据不同的分组类型进行转发</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">APP_AUTH</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 认证信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onAppAuthChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AppAuthData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 插件事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic">// 调用注册的listener对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onPluginChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">RULE</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 规则事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onRuleChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onMetaDataChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">PROXY_SELECTOR</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 代理选择器事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onProxySelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ProxySelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">DISCOVER_UPSTREAM</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 注册发现下游列表事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onDiscoveryUpstreamChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DiscoverySyncData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          applicationContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">LoadServiceDocEntry</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">loadDocOnUpstreamChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DiscoverySyncData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">default</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">IllegalStateException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Unexpected value: "</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>当有数据变更时，调用<code>onApplicationEvent</code>方法，然后遍历所有数据变更监听器，判断是哪种数据类型，交给相应的数据监听器进行处理。</p>
<p><code>ShenYu</code>将所有数据进行了分组，一共会有以下种：认证信息、插件信息、规则信息、选择器信息、元数据、代理选择器、发现下游事件。</p>
<p>这里的数据变更监听器（<code>DataChangedListener</code>），就是数据同步策略的抽象,由特定的实现来处理，而不同的监听由不同的实现来处理，当前分析的是Apollo来
监听，所以这里只关注 <code>ApolloDataChangedListener</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 继承AbstractNodeDataChangedListener</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ApolloDataChangedListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractNodeDataChangedListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>ApolloDataChangedListener</code> 继承了 <code>AbstractNodeDataChangedListener</code> 类，该类主要是以key作为存储方式的基类，如apollo、nacos等，其他的如zookeeper、
consul、etcd 等是以path的方式进行分层级来查找的。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 以key作为查找存储方式的基类</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractNodeDataChangedListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">DataChangedListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">AbstractNodeDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ChangeData</span><span class="token plain"> changeData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">changeData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> changeData</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>AbstractNodeDataChangedListener</code> 接收 <code>ChangeData</code>作为参数，该对象定义了存储于Apollo中的各个数据的key命名，存储于Apollo中的数据包括以下数据：</p>
<ul>
<li class="">插件(plugin)</li>
<li class="">选择器(selector)</li>
<li class="">规则(rule)</li>
<li class="">授权(auth)</li>
<li class="">元数据(meta)</li>
<li class="">代理选择器(proxy.selector)</li>
<li class="">下游列表(discovery)</li>
</ul>
<p>这些信息由ApolloDataChangedListener构造器指定:</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ApolloDataChangedListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractNodeDataChangedListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ApolloDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApolloClient</span><span class="token plain"> apolloClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 配置几类分组数据的前缀</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">super</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ChangeData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RULE_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">AUTH_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PROXY_SELECTOR_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DISCOVERY_DATA_ID</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 操作apollo的对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">apolloClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> apolloClient</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>DataChangedListener</code> 定义了以下几个方法：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 数据变更监听器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> </span><span class="token class-name">DataChangedListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 授权信息变更时调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onAppAuthChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AppAuthData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 插件信息变更时调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onPluginChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息变更时调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据信息变更时调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onMetaDataChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 规则信息变更时调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onRuleChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 代理选择器变更时调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onProxySelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ProxySelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 发现下游信息变更时调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onDiscoveryUpstreamChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DiscoverySyncData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>由 <code>DataChangedEventDispatcher</code>处理插件时，调用方法 <code>listener.onPluginChanged</code>, 接下来分析下对象的逻辑，实现由<code>AbstractNodeDataChangedListener</code>处理：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractNodeDataChangedListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">DataChangedListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onPluginChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 配置前缀为plugin.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> configKeyPrefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> changeData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginDataId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">DefaultNodeConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">JOIN_POINT</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onCommonChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configKeyPrefix</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">debug</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"[DataChangedListener] PluginChanged {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> configKeyPrefix</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>首先构建配置数据的key前缀为：<code>plugin.</code>, 再调用<code>onCommonChanged</code>统一处理：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onCommonChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> configKeyPrefix</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changedList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                     </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Function</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics"> </span><span class="token generics keyword" style="color:#00009f">super</span><span class="token generics"> </span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics"> </span><span class="token generics keyword" style="color:#00009f">extends</span><span class="token generics"> </span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> mapperToKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                     </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> tClass</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// Avoiding concurrent operations on list nodes</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ReentrantLock</span><span class="token plain"> reentrantLock </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> listSaveLockMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">computeIfAbsent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configKeyPrefix</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> key </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ReentrantLock</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            reentrantLock</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">lock</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 当前传入的插件列表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changeNames </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> changedList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">mapperToKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 按 plugin.${pluginName} 进行删除</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    changedList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">mapperToKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">removeKey </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token function" style="color:#d73a49">delConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configKeyPrefix </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> removeKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 从plugin.list中移除对应的插件名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// plugin.list 记录下了目前启用的列表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token function" style="color:#d73a49">delChangedData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configKeyPrefix</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> changeNames</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">REFRESH</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">MYSELF</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 重载逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 获取plugin.list中的所有插件列表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> configDataNames </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getConfigDataNames</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configKeyPrefix</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 依次更新当前调整的每个插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    changedList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changedData </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// 发布配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token function" style="color:#d73a49">publishConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configKeyPrefix </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> mapperToKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changedData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> changedData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 目前存储的列表中，如果数据比当前传入的多，则删除多余的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configDataNames </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> configDataNames</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> changedList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// 踢除当前加载的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        configDataNames</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeNames</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// 逐个删除已经取消的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        configDataNames</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">delConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 重新更新列表数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token function" style="color:#d73a49">publishConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configKeyPrefix </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">DefaultNodeConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">LIST_STR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> changeNames</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">default</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 新增或是更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    changedList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changedData </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token function" style="color:#d73a49">publishConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configKeyPrefix </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> mapperToKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changedData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> changedData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将新加的插件更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token function" style="color:#d73a49">putChangeData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configKeyPrefix</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> changeNames</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Exception</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"AbstractNodeDataChangedListener onCommonMultiChanged error "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">finally</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            reentrantLock</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unlock</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>在以上逻辑，其实包含全量重载(REFRESH、MYSELF)与增量(DELETE、UPDATE、CREATE)的处理</p>
<p>在插件中主要包含两个节点：</p>
<ul>
<li class=""><code>plugin.list</code> 当前生效的插件列表</li>
<li class=""><code>plugin.${plugin.name}</code> 具体插件的详细信息
最后，将这两个节点对应的数据写入Apollo。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="数据初始化">数据初始化<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Apollo-Data-Sync#%E6%95%B0%E6%8D%AE%E5%88%9D%E5%A7%8B%E5%8C%96" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>当<code>admin</code>启动后，会将当前的数据信息全量同步到<code>apollo</code>中，由<code>ApolloDataChangedInit</code>实现：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 继承AbstractDataChangedInit</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ApolloDataChangedInit</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractDataChangedInit</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// apollo操作对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApolloClient</span><span class="token plain"> apolloClient</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ApolloDataChangedInit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApolloClient</span><span class="token plain"> apolloClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">apolloClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> apolloClient</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">notExist</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 判断 plugin、auth、meta、proxy.selector等节点是否存在</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 只要有一个不存在，则进入重新加载(这些节点不会创建，为什么要判断一次呢？)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Stream</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">of</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">AUTH_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PROXY_SELECTOR_DATA_ID</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">allMatch</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">dataIdNotExist</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Data id not exist boolean.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param pluginDataId the plugin data id</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the boolean</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">dataIdNotExist</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginDataId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">apolloClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getItemValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>判断<code>apollo</code>中是否存在数据，如果不存在，则进行同步。
这里有一个bug, 因为这里判断的key，在同步时，并不会创建，则会导致每次重启时都重新加载数据，已提<a href="https://github.com/apache/shenyu/pull/5435" target="_blank" rel="noopener noreferrer" class="">PR#5435</a></p>
<p><code>ApolloDataChangedInit</code>实现了<code>CommandLineRunner</code>接口。它是<code>springboot</code>提供的接口，会在所有 <code>Spring Beans</code>初始化之后执行<code>run()</code>方法，常用于项目中初始化的操作。</p>
<ul>
<li class="">SyncDataService.syncAll()</li>
</ul>
<p>从数据库查询数据，然后进行全量数据同步，所有的认证信息、插件信息、规则信息、选择器信息、元数据、代理选择器、发现下游事件。主要是通过<code>eventPublisher</code>发布同步事件，<code>eventPublisher</code>通过<code>publishEvent()</code>发布完事件后，有<code>ApplicationListener</code>执行事件变更操作，在<code>ShenYu</code>中就是前面提到的<code>DataChangedEventDispatcher</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SyncDataServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 事件发布</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApplicationEventPublisher</span><span class="token plain"> eventPublisher</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">/***</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 全量数据同步</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param type the type</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">syncAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic">// 同步auth数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         appAuthService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">syncData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic">// 同步插件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> pluginDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pluginService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic">// 通过spring发布/订阅机制进行通知订阅者(发布DataChangedEvent)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic">// 统一由DataChangedEventDispatcher进行监听</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic">// DataChangedEvent带上了配置分组类型、当前操作类型、数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic">// 同步选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic">// 同步规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> ruleDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ruleService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RULE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic">//元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         metaDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">syncData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic">// 下游列表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         discoveryService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">syncData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="bootstrap同步操作初始化">bootstrap同步操作初始化<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Apollo-Data-Sync#bootstrap%E5%90%8C%E6%AD%A5%E6%93%8D%E4%BD%9C%E5%88%9D%E5%A7%8B%E5%8C%96" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>网关这边的数据同步初始化操作主要是订阅<code>apollo</code>中的节点，当有数据变更时，收到变更数据。这依赖于<code>apollo</code>的<code>listener</code>机制。在<code>ShenYu</code>中，负责<code>apollo</code>数据同步的是<code>ApolloDataService</code>。</p>
<p><code>ApolloDataService</code>的功能逻辑是在实例化的过程中完成的：对<code>apollo</code>中的<code>shenyu</code>数据同步节点完成订阅。通过<code>configService.addChangeListener()</code>方法实现；</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ApolloDataService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractNodeDataSyncService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ApolloDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Config</span><span class="token plain"> configService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginDataSubscriber</span><span class="token plain"> pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                             </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                             </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AuthDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> authDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                             </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ProxySelectorDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> proxySelectorDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                             </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DiscoveryUpstreamDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> discoveryUpstreamDataSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 配置监听的前缀</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">super</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ChangeData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RULE_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">AUTH_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PROXY_SELECTOR_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DISCOVERY_DATA_ID</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> authDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> proxySelectorDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> discoveryUpstreamDataSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">configService </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> configService</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 开始监听</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 注：Apollo该方法，只负责获取apollo的数据获取，并添加到本地缓存中，不处理监听</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">startWatch</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 配置监听</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">apolloWatchPrefixes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>首先配置需要处理的key信息，同admin同步的key。接着调用<code>startWatch()</code> 方法进行处理数据获取与监听。但对于Apollo的实现中，该方法只负责处理数据的获取并设置到本地缓存中。
监听由<code>apolloWatchPrefixes</code>方法来处理</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apolloWatchPrefixes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 定义监听器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigChangeListener</span><span class="token plain"> listener </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> changeEvent </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            changeEvent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">changedKeys</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigChange</span><span class="token plain"> configChange </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> changeEvent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getChange</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 未变更则跳过</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configChange </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"apollo watchPrefixes error configChange is null {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> changeKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> newValue </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> configChange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getNewValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// skip last is "list"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果是list结尾的Key，如plugin.list则跳过，因为这里只是记录生效的一个列表，不会在本地缓存中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> lastListStrIndex </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> changeKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">length</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token class-name">DefaultNodeConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">LIST_STR</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">length</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">lastIndexOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DefaultNodeConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">LIST_STR</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> lastListStrIndex</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果是plugin.开头 =&gt; 处理插件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">indexOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN_DATA_ID</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// 删除</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyChangeType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETED</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configChange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getChangeType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token comment" style="color:#999988;font-style:italic">// 清除缓存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">unCachePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token comment" style="color:#999988;font-style:italic">// 更新缓存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">cachePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果是selector.开头 =&gt; 处理选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">indexOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR_DATA_ID</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyChangeType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETED</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configChange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getChangeType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">unCacheSelectorData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">cacheSelectorData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果是rule.开头 =&gt; 处理规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">indexOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RULE_DATA_ID</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyChangeType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETED</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configChange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getChangeType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">unCacheRuleData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">cacheRuleData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果是auth.开头 =&gt; 处理授权数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">indexOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">AUTH_DATA_ID</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyChangeType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETED</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configChange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getChangeType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">unCacheAuthData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">cacheAuthData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果是meta.开头 =&gt; 处理元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">indexOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA_ID</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyChangeType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETED</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configChange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getChangeType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">unCacheMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">cacheMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果是proxy.selector.开头 =&gt; 处理代理选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">indexOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PROXY_SELECTOR_DATA_ID</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyChangeType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETED</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configChange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getChangeType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">unCacheProxySelectorData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">cacheProxySelectorData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果是discovery.开头 =&gt; 处理下游列表数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">indexOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DISCOVERY_DATA_ID</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyChangeType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETED</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configChange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getChangeType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">unCacheDiscoveryUpstreamData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changeKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token function" style="color:#d73a49">cacheDiscoveryUpstreamData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Exception</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"apollo sync listener change key handler error"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        watchConfigChangeListener </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> listener</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 添加监听</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        configService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addChangeListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">listener</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">emptySet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ApolloPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">pathKeySet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>由前面admin加载数据的逻辑，插件只会增加两个Key：<code>plugin.list</code> 与 <code>plugin.${plugin.name}</code>,而 <code>plugin.list</code> 是所有启用的插件列表，该key的数据在
本地缓存中没有数据，只会关注<code>plugin.${plugin.name}</code> key对应的数据，这是对应的插件的详细信息。</p>
<p>至此，bootstrap在<code>apollo</code>中的同步逻辑就分析完成。</p>]]></content>
        <author>
            <name>hql0312</name>
            <uri>https://github.com/hql0312</uri>
        </author>
        <category label="apollo" term="apollo"/>
        <category label="data sync" term="data sync"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Etcd数据同步源码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync</id>
        <link href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[Apache ShenYu 是一个异步的，高性能的，跨语言的，响应式的 API 网关。]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p><a href="https://shenyu.apache.org/zh/docs/index" target="_blank" rel="noopener noreferrer" class="">Apache ShenYu</a> 是一个异步的，高性能的，跨语言的，响应式的 <code>API</code> 网关。</p>
</blockquote>
<p>在<code>ShenYu</code>网关中，数据同步是指，当在后台管理系统中，数据发送了更新后，如何将更新的数据同步到网关中。<code>Apache ShenYu</code> 网关当前支持<code>ZooKeeper</code>、<code>WebSocket</code>、<code>Http长轮询</code>、<code>Nacos</code> 、<code>Etcd</code> 和 <code>Consul</code> 进行数据同步。本文的主要内容是基于<code>Etcd</code>的数据同步源码分析。</p>
<blockquote>
<p>本文基于<code>shenyu-2.4.0</code>版本进行源码分析，官网的介绍请参考 <a href="https://shenyu.apache.org/zh/docs/design/data-sync" target="_blank" rel="noopener noreferrer" class="">数据同步原理</a> 。</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-关于etcd">1. 关于Etcd<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#1-%E5%85%B3%E4%BA%8Eetcd" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p><a href="https://github.com/etcd-io/etcd" target="_blank" rel="noopener noreferrer" class=""><code>Etcd</code></a>是一个分布式的键值对存储系统，它为大型分布式计算提供分布式配置服务、同步服务和命名注册。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-admin数据同步">2. Admin数据同步<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#2-admin%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>我们从一个实际案例进行源码追踪，比如在后台管理系统中，对<code>Divide</code>插件中的一条选择器数据进行更新，将权重更新为90：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/update-selector-zh-1f49b39fb8e5ce2c26a80018669619ea.png" width="2385" height="1185" class="img_ev3q"></p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="21-接收数据">2.1 接收数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#21-%E6%8E%A5%E6%94%B6%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">SelectorController.createSelector()</li>
</ul>
<p>进入<code>SelectorController</code>类中的<code>updateSelector()</code>方法，它负责数据的校验，添加或更新数据，返回结果信息。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Validated</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequiredArgsConstructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RestController</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequestMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/selector"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SelectorController</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@PutMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/{id}"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuAdminResult</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">updateSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@PathVariable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"id"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@Valid</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@RequestBody</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 设置当前选择器数据id</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 创建或更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Integer</span><span class="token plain"> updateCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createOrUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 返回结果信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuAdminResult</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">success</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE_SUCCESS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> updateCount</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="22-处理数据">2.2 处理数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#22-%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">SelectorServiceImpl.createOrUpdate()</li>
</ul>
<p>在<code>SelectorServiceImpl</code>类中通过<code>createOrUpdate()</code>方法完成数据的转换，保存到数据库，发布事件，更新<code>upstream</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@RequiredArgsConstructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SelectorServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SelectorService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 负责事件发布的eventPublisher</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApplicationEventPublisher</span><span class="token plain"> eventPublisher</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Transactional</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rollbackFor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createOrUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> selectorCount</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建数据 DTO --&gt; DO</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SelectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorConditionDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorConditionDTOs </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSelectorConditions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 判断是添加还是更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插入选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插入选择器中的条件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setSelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorConditionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorConditionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// check selector add</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 权限检查</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataPermissionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listByUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">JwtUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserInfo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">DataPermissionDTO</span><span class="token plain"> dataPermissionDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataPermissionDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">JwtUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserInfo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setDataId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setDataType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">AdminConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR_DATA_TYPE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataPermissionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildPermissionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 更新数据，先删除再新增</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//delete rule condition then add</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">deleteByQuery</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">SelectorConditionQuery</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setSelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">SelectorConditionDO</span><span class="token plain"> selectorConditionDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SelectorConditionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorConditionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发布事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 更新upstream</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">updateDivideUpstream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> selectorCount</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>在<code>Service</code>类完成数据的持久化操作，即保存数据到数据库，这个比较简单，就不深入追踪了。关于更新<code>upstream</code>操作，放到后面对应的章节中进行分析，重点关注发布事件的操作，它会执行数据同步。</p>
<p><code>publishEvent()</code>方法的逻辑是：找到选择器对应的插件，构建条件数据，发布变更数据。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorConditionDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 找到选择器对应的插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PluginDO</span><span class="token plain"> pluginDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pluginMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selectById</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建条件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConditionData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> conditionDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain">                selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConditionTransfer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">mapToSelectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发布变更数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">transFrom</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> conditionDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>发布变更数据通过<code>eventPublisher.publishEvent()</code>完成，这个<code>eventPublisher</code>对象是一个<code>ApplicationEventPublisher</code>类，这个类的全限定名是<code>org.springframework.context.ApplicationEventPublisher</code>。看到这儿，我们知道了发布数据是通过<code>Spring</code>相关的功能来完成的。</p>
<blockquote>
<p>关于<code>ApplicationEventPublisher</code>：</p>
<p>当有状态发生变化时，发布者调用 <code>ApplicationEventPublisher</code> 的 <code>publishEvent</code> 方法发布一个事件，<code>Spring</code>容器广播事件给所有观察者，调用观察者的 <code>onApplicationEvent</code> 方法把事件对象传递给观察者。调用 <code>publishEvent</code>方法有两种途径，一种是实现接口由容器注入 <code>ApplicationEventPublisher</code> 对象然后调用其方法，另一种是直接调用容器的方法，两种方法发布事件没有太大区别。</p>
<ul>
<li class=""><code>ApplicationEventPublisher</code>：发布事件；</li>
<li class=""><code>ApplicationEvent</code>：<code>Spring</code> 事件，记录事件源、时间和数据；</li>
<li class=""><code>ApplicationListener</code>：事件监听者，观察者；</li>
</ul>
</blockquote>
<p>在<code>Spring</code>的事件发布机制中，有三个对象，</p>
<p>一个是发布事件的<code>ApplicationEventPublisher</code>，在<code>ShenYu</code>中通过构造器注入了一个<code>eventPublisher</code>。</p>
<p>另一个对象是<code>ApplicationEvent</code>，在<code>ShenYu</code>中通过<code>DataChangedEvent</code>继承了它，表示事件对象。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">ApplicationEvent</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>最后一个是 <code>ApplicationListener</code>，在<code>ShenYu</code>中通过<code>DataChangedEventDispatcher</code>类实现了该接口，作为事件的监听者，负责处理事件对象。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEventDispatcher</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataChangedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="23-分发数据">2.3 分发数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#23-%E5%88%86%E5%8F%91%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">DataChangedEventDispatcher.onApplicationEvent()</li>
</ul>
<p>当事件发布完成后，会自动进入到<code>DataChangedEventDispatcher</code>类中的<code>onApplicationEvent()</code>方法，进行事件处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEventDispatcher</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataChangedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 有数据变更时，调用此方法</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param event</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"unchecked"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历数据变更监听器(一般使用一种数据同步的方式就好了)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataChangedListener</span><span class="token plain"> listener </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> listeners</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 哪种数据发生变更</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">APP_AUTH</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 认证信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onAppAuthChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AppAuthData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 插件信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onPluginChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">RULE</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onRuleChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onMetaDataChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">default</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 其他类型，抛出异常</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">IllegalStateException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Unexpected value: "</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>当有数据变更时，调用<code>onApplicationEvent</code>方法，然后遍历所有数据变更监听器，判断是哪种数据类型，交给相应的数据监听器进行处理。</p>
<p><code>ShenYu</code>将所有数据进行了分组，一共是五种：认证信息、插件信息、规则信息、选择器信息和元数据。</p>
<p>这里的数据变更监听器（<code>DataChangedListener</code>），就是数据同步策略的抽象，它的具体实现有：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/data-changed-listener-b01d7410746ca4afd526d8c9df865e9b.png" width="1966" height="482" class="img_ev3q"></p>
<p>这几个实现类就是当前<code>ShenYu</code>支持的同步策略：</p>
<ul>
<li class=""><code>WebsocketDataChangedListener</code>：基于<code>websocket</code>的数据同步；</li>
<li class=""><code>ZookeeperDataChangedListener</code>：基于<code>zookeeper</code>的数据同步；</li>
<li class=""><code>ConsulDataChangedListener</code>：基于<code>consul</code>的数据同步；</li>
<li class=""><code>EtcdDataDataChangedListener</code>：基于<code>etcd</code>的数据同步；</li>
<li class=""><code>HttpLongPollingDataChangedListener</code>：基于<code>http长轮询</code>的数据同步；</li>
<li class=""><code>NacosDataChangedListener</code>：基于<code>nacos</code>的数据同步；</li>
</ul>
<p>既然有这么多种实现策略，那么如何确定使用哪一种呢？</p>
<p>因为本文是基于<code>Etcd</code>的数据同步源码分析，所以这里以<code>EtcdDataDataChangedListener</code>为例，分析它是如何被加载并实现的。</p>
<p>通过查看对<code>EtcdDataDataChangedListener</code>类的调用，可以发现，它是在<code>DataSyncConfiguration</code>类进行配置的。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 数据同步配置类</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 通过springboot条件装配实现</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type Data sync configuration.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataSyncConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">//省略了其他代码......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * The type Etcd listener.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.sync.etcd"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"url"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@EnableConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">EtcdProperties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">EtcdListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">EtcdClient</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">etcdClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">EtcdProperties</span><span class="token plain"> etcdProperties</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">Client</span><span class="token plain"> client </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">endpoints</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">etcdProperties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">EtcdClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">client</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Config event listener data changed listener.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 创建Etcd数据变更监听器</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param etcdClient the etcd client</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the data changed listener</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnMissingBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">EtcdDataDataChangedListener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">DataChangedListener</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">etcdDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">EtcdClient</span><span class="token plain"> etcdClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">EtcdDataDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">etcdClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * data init.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 创建Etcd数据初始化类</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param etcdClient        the etcd client</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param syncDataService the sync data service</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the etcd data init</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnMissingBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">EtcdDataInit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">EtcdDataInit</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">etcdDataInit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">EtcdClient</span><span class="token plain"> etcdClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">EtcdDataInit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">etcdClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//省略了其他代码......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>这个配置类是通过<code>SpringBoot</code>条件装配类实现的。在<code>EtcdListener</code>类上面有几个注解：</p>
<ul>
<li class="">
<p><code>@Configuration</code>：配置文件，应用上下文；</p>
</li>
<li class="">
<p><code>@ConditionalOnProperty(prefix = "shenyu.sync.etcd", name = "url")</code>：属性条件判断，满足条件，该配置类才会生效。也就是说，当我们有如下配置时，就会采用<code>etcd</code>进行数据同步。</p>
<div class="language-properties codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-properties codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key attr-name" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">  sync</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">     etcd</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">          url</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token value attr-value" style="color:#e3116c">localhost:2181</span><br></span></code></pre></div></div>
</li>
<li class="">
<p><code>@EnableConfigurationProperties(EtcdProperties.class)</code>：导入另一个属性类<code>EtcdProperties</code>，<code>EtcdProperties</code>中各属性对应配置文件中以<code>shenyu.sync.etcd</code>作为前缀的各属性。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.sync.etcd"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">EtcdProperties</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Integer</span><span class="token plain"> sessionTimeout</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Integer</span><span class="token plain"> connectionTimeout</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> serializer</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>当我们在配置文件中配置了<code>shenyu.sync.etcd.url</code>属性时，<code>Admin</code>将采用<code>etcd</code>进行数据同步，此时配置类<code>EtcdListener</code>会生效，并生成<code>EtcdClient</code>, <code>EtcdDataDataChangedListener</code>和<code>EtcdDataInit</code>类型的bean。</p>
<ul>
<li class="">生成<code>EtcdClient</code>类型的bean，<code>etcdClient</code>，这个bean根据配置文件，配置了与etcd服务器的连接信息，可以直接操作etcd节点。</li>
<li class="">生成<code>EtcdDataDataChangedListener</code>类型的bean，<code>etcdDataDataChangedListener</code>，这个bean将bean<code>etcdClient</code>作为成员变量，当监听到事件时，进行回调操作，可以直接使用该bean操作etcd节点。</li>
<li class="">生成<code>EtcdDataInit</code>类型的bean，<code>etcdDataInit</code>，这个bean将bean<code>etcdClient</code>和bean<code>syncDataService</code>作为成员变量，使用<code>etcdClient</code>根据etcd路径，判断数据是否未初始化，当未初始化时，将调用syncDataService进行刷新操作，将在下文详述。
根据上文所述，在事件处理方法<code>onApplicationEvent()</code>中，就会到相应的<code>listener</code>中。在我们的案例中，是对一条选择器数据进行更新，数据同步采用的是<code>etcd</code>，所以，代码会进入到<code>EtcdDataDataChangedListener</code>进行选择器数据变更处理。</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//DataChangedEventDispatcher.java</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"unchecked"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历数据变更监听器(一般使用一种数据同步的方式就好了)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataChangedListener</span><span class="token plain"> listener </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> listeners</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 哪种数据发生变更</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 省略了其他逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 在我们的案例中，会进入到EtcdDataDataChangedListener进行选择器数据变更处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-etcd数据变更监听器">2.4 Etcd数据变更监听器<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#24-etcd%E6%95%B0%E6%8D%AE%E5%8F%98%E6%9B%B4%E7%9B%91%E5%90%AC%E5%99%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">
<p>EtcdDataDataChangedListener.onSelectorChanged()</p>
<p>在<code>onSelectorChanged()</code>方法中，判断操作类型，是刷新同步还是更新或创建同步。根据当前选择器数据信息判断节点是否在<code>etcd</code>中。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * EtcdDataDataChangedListener.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Slf4j</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">EtcdDataDataChangedListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">DataChangedListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">EtcdClient</span><span class="token plain"> etcdClient</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">EtcdDataDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">EtcdClient</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">etcdClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息发生改变</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 刷新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">eventType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">REFRESH</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">changed</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> selectorParentPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorParentPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changed</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        etcdClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">deleteEtcdPathRecursive</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorParentPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 发生变更的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorData</span><span class="token plain"> data </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建选择器数据的真实路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> selectorRealPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorRealPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">eventType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          etcdClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">delete</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorRealPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">continue</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//create or update，创建或更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">updateNode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorRealPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>这部分是核心。<code>changed</code>表示需更新的<code>SelectorData</code>列表，<code>eventType</code>表示事件类型。当事件类型为刷新<code>REFRESH</code>，并且<code>SelectorData</code>有改动时，会先将etcd中该plugin下的selector节点都先删除。注意这里的条件<code>SelectorData</code>有改动是必须的，否则会出现没有改动时进行刷新，将所有selector节点都删除的bug。
获取到selector对应路径后，会对节点进行删除、创建或更新。</p>
<p>只要将变动的数据正确写入到<code>etcd</code>的节点上，<code>admin</code>这边的操作就执行完成了。</p>
<p>在我们当前的案例中，对<code>Divide</code>插件中的一条选择器数据进行更新，将权重更新为90，就会对图中的特定节点更新。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/zookeeper-node-c7628b680a1f1afa0eada97b66fcd5b1.png" width="1704" height="1140" class="img_ev3q"></p>
<p>我们用时序图将上面的更新流程串联起来。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/etcd-sync-sequence-admin-zh-d9ccd2c6bd5f9b3f135c5420b60fd403.png" width="1663" height="634" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-网关数据同步">3. 网关数据同步<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#3-%E7%BD%91%E5%85%B3%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>假设<code>ShenYu</code>网关已经在正常运行，使用的数据同步方式也是<code>etcd</code>。那么当在<code>admin</code>端更新选择器数据后，并且向<code>etcd</code>发送了变更的数据，那网关是如何接收并处理数据的呢？接下来我们就继续进行源码分析，一探究竟。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="31-etcdclient接收数据">3.1 EtcdClient接收数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#31-etcdclient%E6%8E%A5%E6%94%B6%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">EtcdClient.watchDataChange()</li>
</ul>
<p>在网关端有一个<code>EtcdSyncDataService</code>类，它通过<code>etcdClient</code>订阅了数据节点，当数据发生变更时，可以感知到。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Data synchronize of etcd.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Slf4j</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">EtcdSyncDataService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">AutoCloseable</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//省略其它代码</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">subscribeSelectorDataChanges</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      etcdClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">watchDataChange</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">updateNode</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> updateValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">cacheSelectorData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">updateValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">unCacheSelectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">//省略其它代码</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>Etcd</code>的<code>Watch</code>机制，会给订阅的客户端发送节点变更通知。在我们的案例中，更新选择器信息，就会进入到<code>watchDataChange()</code>方法。通过<code>cacheSelectorData()</code>去处理数据。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="32-处理数据">3.2 处理数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#32-%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">EtcdSyncDataService.cacheSelectorData()</li>
</ul>
<p>经过判空逻辑之后，缓存选择器数据的操作又交给了<code>PluginDataSubscriber</code>处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">cacheSelectorData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> dataString</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataString</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSelectorSubscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>PluginDataSubscriber</code>是一个接口，它只有一个<code>CommonPluginDataSubscriber</code>实现类，负责处理插件、选择器和规则数据。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="33-通用插件数据订阅者">3.3 通用插件数据订阅者<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#33-%E9%80%9A%E7%94%A8%E6%8F%92%E4%BB%B6%E6%95%B0%E6%8D%AE%E8%AE%A2%E9%98%85%E8%80%85" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">PluginDataSubscriber.onSelectorSubscribe()</li>
</ul>
<p>它没有其他逻辑，直接调用<code>subscribeDataHandler()</code>方法。在方法中，更具数据类型（插件、选择器或规则），操作类型（更新或删除），去执行不同逻辑。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 通用插件数据订阅者，负责处理所有插件、选择器和规则信息</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type Common plugin data subscriber.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">CommonPluginDataSubscriber</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">PluginDataSubscriber</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">// 处理选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onSelectorSubscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">subscribeDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅数据处理器，处理数据的更新或删除</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">subscribeDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token plain"> classData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> dataType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">classData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">PluginData</span><span class="token plain"> pluginData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cachePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handlerPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 从网关内存移除数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removePlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cacheSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理                    Optional.ofNullable(handlerMap.get(selectorData.getPluginName())).ifPresent(handler -&gt; handler.handlerSelector(selectorData));</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 从网关内存移除数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">RuleData</span><span class="token plain"> ruleData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RuleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cacheRuleData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handlerRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 从网关内存移除数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeRuleData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="34-数据缓存到内存">3.4 数据缓存到内存<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#34-%E6%95%B0%E6%8D%AE%E7%BC%93%E5%AD%98%E5%88%B0%E5%86%85%E5%AD%98" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>那么更新一条选择器数据，会进入下面的逻辑：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cacheSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理                    </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handlerSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>一是将数据保存到网关的内存中。<code>BaseDataCache</code>是最终缓存数据的类，通过单例模式实现。选择器数据就存到了<code>SELECTOR_MAP</code>这个<code>Map</code>中。在后续使用的时候，也是从这里拿数据。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 私有变量</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  	</span><span class="token comment" style="color:#999988;font-style:italic">// 私有构造器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Gets instance.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *  公开方法</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the instance</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">    *  缓存选择器数据的Map</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * pluginName -&gt; SelectorData.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConcurrentMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Maps</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newConcurrentMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">cacheSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">selectorAccept</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * cache selector data.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 缓存选择器数据</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param data the selector data</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">selectorAccept</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">containsKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作，先删除再插入</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> existList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> resultList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> existList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">r </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">r</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            resultList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> collect </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> resultList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sorted</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Comparator</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comparing</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorData</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">getSort</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> collect</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 新增操作，直接放到Map中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Lists</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newArrayList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>二是如果每个插件还有自己的处理逻辑，那么就去处理。  通过<code>idea</code>编辑器可以看到，当新增一条选择器后，有如下的插件还有处理。这里我们就不再展开了。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/handler-selector-bf05b8fdf80a428aa53606178a42bae6.png" width="2456" height="617" class="img_ev3q"></p>
<p>经过以上的源码追踪，并通过一个实际的案例，在<code>admin</code>端新增更新一条选择器数据，就将<code>etcd</code>数据同步的流程分析清楚了。</p>
<p>我们还是通过时序图将网关端的数据同步流程串联一下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/etcd-sync-sequence-gateway-zh-708de62d8fafbb80c133b20247674db6.png" width="1115" height="634" class="img_ev3q"></p>
<p>数据同步的流程已经分析完了，为了不让同步流程被打断，在分析过程中就忽略了其他逻辑。我们还需要分析<code>Admin</code>同步数据初始化和网关同步操作初始化的流程。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-admin同步数据初始化">4. Admin同步数据初始化<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#4-admin%E5%90%8C%E6%AD%A5%E6%95%B0%E6%8D%AE%E5%88%9D%E5%A7%8B%E5%8C%96" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>当<code>admin</code>启动后，会将当前的数据信息全量同步到<code>etcd</code>中，实现逻辑如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * EtcdDataInit.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Slf4j</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">EtcdDataInit</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">CommandLineRunner</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">EtcdClient</span><span class="token plain"> etcdClient</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">EtcdDataInit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">EtcdClient</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">etcdClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">syncDataService </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> args</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN_PARENT</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> authPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APP_AUTH_PARENT</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> metaDataPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">etcdClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">etcdClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">etcdClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Init all data from database"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      syncDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">syncAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">REFRESH</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>判断<code>etcd</code>中是否存在数据，如果不存在，则进行同步。</p>
<p><code>EtcdDataInit</code>实现了<code>CommandLineRunner</code>接口。它是<code>springboot</code>提供的接口，会在所有 <code>Spring Beans</code>初始化之后执行<code>run()</code>方法，常用于项目中初始化的操作。</p>
<ul>
<li class="">SyncDataService.syncAll()</li>
</ul>
<p>从数据库查询数据，然后进行全量数据同步，所有的认证信息、插件信息、选择器信息、规则信息和元数据信息。主要是通过<code>eventPublisher</code>发布同步事件。这里就跟前面提到的同步逻辑就又联系起来了，<code>eventPublisher</code>通过<code>publishEvent()</code>发布完事件后，有<code>ApplicationListener</code>执行事件变更操作，在<code>ShenYu</code>中就是前面提到的<code>DataChangedEventDispatcher</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SyncDataServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 事件发布</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApplicationEventPublisher</span><span class="token plain"> eventPublisher</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">/***</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 全量数据同步</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param type the type</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">syncAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步认证信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        appAuthService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">syncData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步插件信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> pluginDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pluginService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> ruleDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ruleService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RULE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步元数据信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        metaDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">syncData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-网关同步操作初始化">5. 网关同步操作初始化<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#5-%E7%BD%91%E5%85%B3%E5%90%8C%E6%AD%A5%E6%93%8D%E4%BD%9C%E5%88%9D%E5%A7%8B%E5%8C%96" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>网关这边的数据同步初始化操作主要是订阅<code>etcd</code>中的节点，当有数据变更时，收到变更数据。这依赖于<code>Etcd</code>的<code>Watch</code>机制。在<code>ShenYu</code>中，负责<code>etcd</code>数据同步的是<code>EtcdSyncDataService</code>，也在前面提到过。</p>
<p><code>EtcdSyncDataService</code>的功能逻辑是在实例化的过程中完成的：对<code>etcd</code>中的<code>shenyu</code>数据同步节点完成订阅。这里的订阅分两类，一类是已经存在的节点上面数据发生更新，这通过<code>etcdClient.watchDataChange()</code>方法实现；另一类是当前节点下有新增或删除节点，即子节点发生变化，这通过<code>etcdClient.watchChildChange()</code>方法实现。</p>
<p><code>EtcdSyncDataService</code>的代码有点多，这里我们以插件数据的读取和订阅进行追踪，其他类型的数据操作原理是一样的。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * etcd 数据同步服务</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Slf4j</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">EtcdSyncDataService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">AutoCloseable</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 在实例化的时候，完成从etcd中读取数据的操作，并订阅节点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">EtcdSyncDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token comment" style="color:#999988;font-style:italic">/*省略构造参数*/</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">etcdClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> etcdClient</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">pluginDataSubscriber </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">metaDataSubscribers </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">authDataSubscribers </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> authDataSubscribers</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅插件、选择器和规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">watcherData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅认证数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">watchAppAuth</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">watchMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">watcherData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 插件节点路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginParent </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN_PARENT</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 所有插件节点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> pluginZKs </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">etcdClientGetChildren</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginParent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> pluginName </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> pluginZKs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅当前所有插件、选择器和规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token function" style="color:#d73a49">watcherAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅子节点（新增或删除一个插件）</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    etcdClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">watchChildChange</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginParent</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">updateNode</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> updateValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">updateNode</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 需要订阅子节点的所有插件、选择器和规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">watcherAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">updateNode</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">watcherAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅插件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">watcherPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">watcherSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">watcherRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">watcherPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 当前插件路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> pluginPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildPluginPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 缓存到网关内存中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">cachePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">etcdClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅插件节点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">subscribePluginDataChanges</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">cachePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> dataString</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token plain"> pluginData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataString</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flatMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSubscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">subscribePluginDataChanges</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅数据变更：更新或删除，两个lambda表达式分别为更新和删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    etcdClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">watchDataChange</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">updatePath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> updateValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> dataPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRealPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> updatePath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> dataStr </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> etcdClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token plain"> data </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataStr</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">d </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSubscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">d</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> deleteNode </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">deletePlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>上面的源代码中都给出了注释，相信大家可以看明白。订阅插件数据的主要逻辑如下：</p>
<blockquote>
<ol>
<li class="">构造当前插件路径</li>
<li class="">读取etcd上当前节点数据，并反序列化</li>
<li class="">插件数据缓存到网关内存中</li>
<li class="">订阅插件节点</li>
</ol>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-总结">6. 总结<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Etcd-Data-Sync#6-%E6%80%BB%E7%BB%93" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>本文通过一个实际案例，对<code>etcd</code>的数据同步原理进行了源码分析。涉及到的主要知识点如下：</p>
<ul>
<li class="">基于<code>etcd</code>的数据同步，主要是通过<code>watch</code>机制实现；</li>
<li class="">通过<code>Spring</code>完成事件发布和监听；</li>
<li class="">通过抽象<code>DataChangedListener</code>接口，支持多种同步策略，面向接口编程；</li>
<li class="">使用单例设计模式实现缓存数据类<code>BaseDataCache</code>；</li>
<li class="">通过<code>SpringBoot</code>的条件装配和<code>starter</code>加载机制实现配置类的加载。</li>
</ul>]]></content>
        <author>
            <name>4zd</name>
            <uri>https://github.com/4zd</uri>
        </author>
        <category label="etcd" term="etcd"/>
        <category label="data sync" term="data sync"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Http长轮询数据同步源码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync</id>
        <link href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[Apache ShenYu 是一个异步的，高性能的，跨语言的，响应式的 API 网关。]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p><a href="https://shenyu.apache.org/zh/docs/index" target="_blank" rel="noopener noreferrer" class="">Apache ShenYu</a> 是一个异步的，高性能的，跨语言的，响应式的 <code>API</code> 网关。</p>
</blockquote>
<p>在<code>ShenYu</code>网关中，数据同步是指，当在后台管理系统中，数据发送了更新后，如何将更新的数据同步到网关中。<code>Apache ShenYu</code> 网关当前支持<code>ZooKeeper</code>、<code>WebSocket</code>、<code>Http长轮询</code>、<code>Nacos</code> 、<code>Etcd</code> 和 <code>Consul</code> 进行数据同步。本文的主要内容是基于<code>Http长轮询</code>的数据同步源码分析。</p>
<blockquote>
<p>本文基于<code>shenyu-2.5.0</code>版本进行源码分析，官网的介绍请参考 <a href="https://shenyu.apache.org/zh/docs/design/data-sync" target="_blank" rel="noopener noreferrer" class="">数据同步原理</a> 。</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-http长轮询">1. Http长轮询<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#1-http%E9%95%BF%E8%BD%AE%E8%AF%A2" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>这里直接引用官网的相关描述：</p>
<blockquote>
<p><code>Zookeeper</code>和<code>WebSocket</code> 数据同步的机制比较简单，而 <code>Http长轮询</code>则比较复杂。 <code>Apache ShenYu</code> 借鉴了 <code>Apollo</code>、<code>Nacos</code> 的设计思想，取其精华，自己实现了 <code>Http长轮询</code>数据同步功能。注意，这里并非传统的 <code>ajax</code> 长轮询！</p>
</blockquote>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/http-long-polling-zh-bc8bd8fe6c4aa883a959f59fce05078a.png" width="1852" height="863" class="img_ev3q"></p>
<p><code>Http长轮询</code> 机制如上所示，<code>Apache ShenYu</code>网关主动请求 <code>shenyu-admin</code> 的配置服务，读取超时时间为 <code>90s</code>，意味着网关层请求配置服务最多会等待 <code>90s</code>，这样便于 <code>shenyu-admin</code> 配置服务及时响应变更数据，从而实现准实时推送。</p>
<p><code>Http长轮询</code> 机制是由网关主动请求 <code>shenyu-admin</code> ，所以这次的源码分析，我们从网关这一侧开始。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-网关数据同步">2. 网关数据同步<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#2-%E7%BD%91%E5%85%B3%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="21-加载配置">2.1 加载配置<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#21-%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p><code>Http长轮询</code> 数据同步配置的加载是通过<code>spring boot</code>的<code>starter</code>机制，当我们引入相关依赖和在配置文件中有如下配置时，就会加载。</p>
<p>在<code>pom</code>文件中引入依赖：</p>
<div class="language-xml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-xml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">&lt;!--shenyu data sync start use http--&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">dependency</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">groupId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">org.apache.shenyu</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">groupId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">artifactId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">shenyu-spring-boot-starter-sync-data-http</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">artifactId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">version</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">${project.version}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">version</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">dependency</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<p>在<code>application.yml</code>配置文件中添加配置：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">sync</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       </span><span class="token key atrule" style="color:#00a4db">http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">url</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//localhost</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">9095</span><br></span></code></pre></div></div>
<p>当网关启动时，配置类<code>HttpSyncDataConfiguration</code>就会执行，加载相应的<code>Bean</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Http sync data configuration for spring boot.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnClass</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpSyncDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.sync.http"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"url"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@EnableConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">HttpConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpSyncDataConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Logger</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LOGGER</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">LoggerFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLogger</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpSyncDataConfiguration</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * Rest template.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * 创建RestTemplate</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param httpConfig the http config       http配置</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @return the rest template</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">RestTemplate</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">restTemplate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpConfig</span><span class="token plain"> httpConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">OkHttp3ClientHttpRequestFactory</span><span class="token plain"> factory </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">OkHttp3ClientHttpRequestFactory</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    factory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setConnectTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">httpConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getConnectionTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token class-name">HttpConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CLIENT_POLLING_CONNECT_TIMEOUT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> httpConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getConnectionTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    factory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setReadTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">httpConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getReadTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token class-name">HttpConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CLIENT_POLLING_READ_TIMEOUT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> httpConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getReadTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    factory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setWriteTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">httpConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getWriteTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token class-name">HttpConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CLIENT_POLLING_WRITE_TIMEOUT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> httpConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getWriteTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">RestTemplate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">factory</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * AccessTokenManager.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * 创建AccessTokenManager,专门用户对admin进行http请求时access token的处理</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param httpConfig   the http config.      </span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param restTemplate the rest template.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @return the access token manager.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">AccessTokenManager</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">accessTokenManager</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpConfig</span><span class="token plain"> httpConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RestTemplate</span><span class="token plain"> restTemplate</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">AccessTokenManager</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">restTemplate</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> httpConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * Http sync data service.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * 创建 HttpSyncDataService </span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param httpConfig         the http config</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param pluginSubscriber   the plugin subscriber</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param restTemplate       the rest template</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param metaSubscribers    the meta subscribers</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param authSubscribers    the auth subscribers</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param accessTokenManager the access token manager</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @return the sync data service</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">httpSyncDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">HttpConfig</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> httpConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                             </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> pluginSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                             </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RestTemplate</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> restTemplate</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                             </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                             </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AuthDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> authSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                             </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AccessTokenManager</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> accessTokenManager</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">LOGGER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"you use http long pull sync shenyu data"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">HttpSyncDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">requireNonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">httpConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">requireNonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginSubscriber</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">requireNonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">restTemplate</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaSubscribers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collections</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">emptyList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            authSubscribers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collections</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">emptyList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">requireNonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">accessTokenManager</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p><code>HttpSyncDataConfiguration</code>是<code>Http长轮询</code>数据同步的配置类，负责创建<code>HttpSyncDataService</code>（负责<code>http</code>数据同步的具体实现）、<code>RestTemplate</code>和<code>AccessTokenManager</code> （负责与<code>admin</code>http调用时access token的处理）。它的注解如下：</p>
<ul>
<li class=""><code>@Configuration</code>：表示这是一个配置类；</li>
<li class=""><code>@ConditionalOnClass(HttpSyncDataService.class)</code>：条件注解，表示要有<code>HttpSyncDataService</code>这个类；</li>
<li class=""><code>@ConditionalOnProperty(prefix = "shenyu.sync.http", name = "url")</code>：条件注解，要有<code>shenyu.sync.http.url</code>这个属性配置。</li>
<li class=""><code>@EnableConfigurationProperties(value = HttpConfig.class)</code>：表示让HttpConfig上的注解<code>@ConfigurationProperties(prefix = "shenyu.sync.http")</code>生效，将<code>HttpConfig</code>这个配置类注入Ioc容器中。</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="22-属性初始化">2.2 属性初始化<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#22-%E5%B1%9E%E6%80%A7%E5%88%9D%E5%A7%8B%E5%8C%96" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">HttpSyncDataService</li>
</ul>
<p>在<code>HttpSyncDataService</code>的构造函数中，完成属性初始化。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpSyncDataService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 省略了属性字段......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">HttpSyncDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpConfig</span><span class="token plain"> httpConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                               </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginDataSubscriber</span><span class="token plain"> pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                               </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RestTemplate</span><span class="token plain"> restTemplate</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                               </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                               </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AuthDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> authDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                               </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">AccessTokenManager</span><span class="token plain"> accessTokenManager</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic">// 1.设置accessTokenManager</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">accessTokenManager </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> accessTokenManager</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic">// 2.创建数据处理器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">factory </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataRefreshFactory</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> authDataSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic">// 3.shenyu-admin的url， 多个用逗号(,)分割</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">serverList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Lists</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newArrayList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Splitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">on</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">","</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">split</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">httpConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic">// 4.只用于http长轮询的restTemplate</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">restTemplate </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> restTemplate</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic">// 5.开始执行长轮询任务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>上面代码中省略了其他函数和相关字段，在构造函数中完成属性的初始化，主要是：</p>
<ul>
<li class="">
<p>设置<code>accessTokenManager</code>，定时向<code>admin</code>请求更新<code>accessToken</code>的值。然后每次向<code>admin</code>发起请求时都必须将<code>header</code>的<code>X-Access-Token</code>属性设置成<code>accessToken</code>对应的值；</p>
</li>
<li class="">
<p>创建数据处理器，用于后续缓存各种类型的数据（插件、选择器、规则、元数据和认证数据）；</p>
</li>
<li class="">
<p>获取<code>admin</code>属性配置，主要是获取<code>admin</code>的<code>url</code>，<code>admin</code>有可能是集群，多个用逗号<code>(,)</code>分割；</p>
</li>
<li class="">
<p>设置<code>RestTemplate</code>，用于向<code>admin</code>发起请求；</p>
</li>
<li class="">
<p>开始执行长轮询任务。</p>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="23-开始长轮询">2.3 开始长轮询<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#23-%E5%BC%80%E5%A7%8B%E9%95%BF%E8%BD%AE%E8%AF%A2" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">HttpSyncDataService#start()</li>
</ul>
<p>在<code>start()</code>方法中，干了两件事情，一个是获取全量数据，即请求<code>admin</code>端获取所有需要同步的数据，然后将获取到的数据缓存到网关内存中。另一个是开启多线程执行长轮询任务。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpSyncDataService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// // 只初始化一次，通过原子类实现。 </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">RUNNING</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">compareAndSet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 初次启动，获取全量数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fetchGroupConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">values</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 一个后台服务，一个线程</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> threadSize </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> serverList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 自定义线程池</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">executor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">threadSize</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> threadSize</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">60L</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SECONDS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">LinkedBlockingQueue</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">ShenyuThreadFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"http-long-polling"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 开始长轮询，一个admin服务，创建一个线程用于数据同步</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">serverList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">server </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">executor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">HttpLongPollingTask</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">server</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"shenyu http long polling was started, executor=[{}]"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> executor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="231-获取全量数据">2.3.1 获取全量数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#231-%E8%8E%B7%E5%8F%96%E5%85%A8%E9%87%8F%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h5>
<ul>
<li class="">HttpSyncDataService#fetchGroupConfig()</li>
</ul>
<p><code>ShenYu</code>将所有需要同步的数据进行了分组，一共有5种数据类型，分别是插件、选择器、规则、元数据和认证数据。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">enum</span><span class="token plain"> </span><span class="token class-name">ConfigGroupEnum</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">APP_AUTH</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 认证数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">RULE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>admin</code>有可能是集群，这里通过循环的方式向每个<code>admin</code>发起请求，有一个执行成功了，那么向<code>admin</code>获取全量数据并缓存到网关的操作就执行成功。如果出现了异常，就向下一个<code>admin</code>发起请求。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpSyncDataService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">fetchGroupConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> groups</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// admin有可能是集群，这里通过循环的方式向每个admin发起请求</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> index </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> index </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">serverList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> index</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">String</span><span class="token plain"> server </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> serverList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">index</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 真正去执行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doFetchGroupConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">server</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> groups</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 有一个成功，就成功了，可以退出循环</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 出现异常，尝试执行下一个</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 最后一个也执行失败了，抛出异常</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">index </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> serverList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">warn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"fetch config fail, try another one: {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> serverList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">index </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">HttpSyncDataService#doFetchGroupConfig()</li>
</ul>
<p>在此方法中，首先拼装请求参数，然后通过<code>httpClient</code>发起请求，到<code>admin</code>中获取数据，最后将获取到的数据更新到网关内存中。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpSyncDataService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doFetchGroupConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> server</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> groups</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 1. 拼请求参数，所有分组枚举类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">StringBuilder</span><span class="token plain"> params </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">StringBuilder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token plain"> groupKey </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> groups</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      params</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">append</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"groupKeys"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">append</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"="</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">append</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">groupKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">append</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"&amp;"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// admin端提供的接口  /configs/fetch</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> url </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> server </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SHENYU_ADMIN_PATH_CONFIGS_FETCH</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"?"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeEnd</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">params</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"&amp;"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"request configs: [{}]"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">HttpHeaders</span><span class="token plain"> headers </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">HttpHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 设置accessToken</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      headers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">X_ACCESS_TOKEN</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">accessTokenManager</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAccessToken</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">HttpEntity</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> httpEntity </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">HttpEntity</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">headers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 2. 发起请求，获取变更数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      json </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">restTemplate</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exchange</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">url</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">HttpMethod</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">GET</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> httpEntity</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBody</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RestClientException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">String</span><span class="token plain"> message </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">format</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"fetch config fail from server[%s], %s"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">warn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 3. 更新网关内存中数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> updated </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateCacheWithJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">updated</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">debug</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"get latest configs: [{}]"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 更新成功，此方法就执行完成了</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"The config of the server[{}] has not been updated or is out of date. Wait for 30s to listen for changes again."</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> server</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 服务端没有数据更新，就等30s</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ThreadUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sleep</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SECONDS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>从代码中，可以看到 <code>admin</code>端提供的获取全量数据接口是  <code>/configs/fetch</code>，这里先不进一步深入，放在后文再分析。</p>
<p>获取到<code>admin</code>返回结果数据，并成功更新，那么此方法就执行结束了。如果没有更新成功，那么有可能是服务端没有数据更新，就等待<code>30s</code>。</p>
<p>这里需要提前说明一下，网关在判断是否更新成功时，有比对数据的操作，马上就会提到。</p>
<ul>
<li class="">HttpSyncDataService#updateCacheWithJson()</li>
</ul>
<p>更新网关内存中的数据。使用<code>GSON</code>进行反序列化，从属性<code>data</code>中拿真正的数据，然后交给<code>DataRefreshFactory</code>去做更新。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">updateCacheWithJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 使用GSON进行反序列化</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">JsonObject</span><span class="token plain"> jsonObject </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">GSON</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">json</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">JsonObject</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// if the config cache will be updated?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> factory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">executor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">jsonObject</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAsJsonObject</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"data"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">DataRefreshFactory#executor()</li>
</ul>
<p>根据不同数据类型去更新数据，返回更新结果。具体更新逻辑交给了<code>dataRefresh.refresh()</code>方法。在更新结果中，有一种数据类型进行了更新，就表示此次操作发生了更新。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">executor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">JsonObject</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//并行更新数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Boolean</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">ENUM_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">values</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parallelStream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataRefresh </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> dataRefresh</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">refresh</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//有一个更新就表示此次发生了更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">anyMatch</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">AbstractDataRefresh#refresh()</li>
</ul>
<p>数据更新逻辑采用的是模板方法设计模式，通用操作在抽象方法中完成，不同的实现逻辑由子类完成。5种数据类型具体的更新逻辑有些差异，但是也存在通用的更新逻辑，类图关系如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/data-refresh-a5628c71ea221ffb0a7a45f4ed40ae0e.png" width="1848" height="419" class="img_ev3q"></p>
<p>在通用的<code>refresh()</code>方法中，负责数据类型转换，判断是否需要更新，和实际的数据刷新操作。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractDataRefresh</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">DataRefresh</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">refresh</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">JsonObject</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 数据类型转换</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">JsonObject</span><span class="token plain"> jsonObject </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">convert</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">jsonObject</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> updated </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 得到数据类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ConfigData</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">jsonObject</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 是否需要更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateCacheIfNeed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      updated </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 真正的更新逻辑，数据刷新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token function" style="color:#d73a49">refresh</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> updated</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">AbstractDataRefresh#updateCacheIfNeed()</li>
</ul>
<p>数据转换的过程，就是根据不同的数据类型进行转换，我们就不再进一步追踪了，看看数据是否需要更新的逻辑。方法名是<code>updateCacheIfNeed()</code>，通过方法重载实现。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractDataRefresh</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">DataRefresh</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// result是数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">updateCacheIfNeed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigData</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// newVal是获取到的最新的值</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// groupEnum 是哪种数据类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">updateCacheIfNeed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigData</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> newVal</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigGroupEnum</span><span class="token plain"> groupEnum</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果是第一次，那么直接放到cache中，返回 true，表示此次进行了更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">GROUP_CACHE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">putIfAbsent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">groupEnum</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> newVal</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ResultHolder</span><span class="token plain"> holder </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ResultHolder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">GROUP_CACHE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">merge</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">groupEnum</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> newVal</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">oldVal</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> value</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// md5 值相同，不需要更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">oldVal</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMd5</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> newVal</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMd5</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Get the same config, the [{}] config cache will not be updated, md5:{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> groupEnum</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> oldVal</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMd5</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> oldVal</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 当前缓存的数据修改时间大于 新来的数据，不需要更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// must compare the last update time</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">oldVal</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLastModifyTime</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> newVal</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLastModifyTime</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Last update time earlier than the current configuration, the [{}] config cache will not be updated"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> groupEnum</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> oldVal</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"update {} config: {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> groupEnum</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> newVal</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      holder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> newVal</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> holder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>从上面的源码中可以看到，有两种情况不需要更新：</p>
<ul>
<li class="">两个的数据的<code>md5</code> 值相同，不需要更新;</li>
<li class="">当前缓存的数据修改时间大于 新来的数据，不需要更新。</li>
</ul>
<p>其他情况需要更新数据。</p>
<p>分析到这里，就将<code>start()</code> 方法中初次启动，获取全量数据的逻辑分析完了，接下来是长轮询的操作。为了方便，我将<code>start()</code>方法再粘贴一次：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpSyncDataService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// // 只初始化一次，通过原子类实现。 </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">RUNNING</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">compareAndSet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 初次启动，获取全量数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fetchGroupConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">values</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 一个后台服务，一个线程</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> threadSize </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> serverList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 自定义线程池</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">executor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ThreadPoolExecutor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">threadSize</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> threadSize</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">60L</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SECONDS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">LinkedBlockingQueue</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token class-name">ShenyuThreadFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"http-long-polling"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 开始长轮询，一个admin服务，创建一个线程用于数据同步</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">serverList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">server </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">executor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">HttpLongPollingTask</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">server</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"shenyu http long polling was started, executor=[{}]"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> executor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="232-执行长轮询任务">2.3.2 执行长轮询任务<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#232-%E6%89%A7%E8%A1%8C%E9%95%BF%E8%BD%AE%E8%AF%A2%E4%BB%BB%E5%8A%A1" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h5>
<ul>
<li class="">HttpLongPollingTask#run()</li>
</ul>
<p>长轮询任务是<code>HttpLongPollingTask</code>，它实现了<code>Runnable</code>接口，任务逻辑在<code>run()</code>方法中。通过<code>while()</code>循环实现不断执行任务，即长轮询。在每一次的轮询中有三次重试逻辑，一次轮询任务失败了，等 <code>5s</code> 再继续，<code>3</code> 次都失败了，等<code>5</code> 分钟再试。</p>
<p>开始长轮询，一个<code>admin</code>服务，创建一个线程用于数据同步。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpLongPollingTask</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">Runnable</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> server</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token class-name">HttpLongPollingTask</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> server</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">server </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> server</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 一直轮询</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">RUNNING</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 默认重试 3 次</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> retryTimes </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> time </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> time </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> retryTimes</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> time</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token function" style="color:#d73a49">doLongPolling</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">server</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Exception</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">time </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> retryTimes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">warn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Long polling failed, tried {} times, {} times left, will be suspended for a while! {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    time</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> retryTimes </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> time</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 长轮询失败了，等 5s 再继续</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ThreadUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sleep</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SECONDS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">continue</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Long polling failed, try again after 5 minutes!"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic">// 3 次都失败了，等 5 分钟再试</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token class-name">ThreadUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sleep</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">MINUTES</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">warn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Stop http long polling."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">HttpSyncDataService#doLongPolling()</li>
</ul>
<p>执行长轮询任务的核心逻辑：</p>
<ul>
<li class="">根据数据类型组装请求参数：<code>md5</code> 和 <code>lastModifyTime</code>；</li>
<li class="">组装请求头和请求体；</li>
<li class="">向<code>admin</code>发起请求，判断组数据是否发生变更；</li>
<li class="">根据发生变更的组，再去获取数据。</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpSyncDataService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doLongPolling</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> server</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 组装请求参数：md5 和 lastModifyTime</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">MultiValueMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> params </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">LinkedMultiValueMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token plain"> group </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">values</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">ConfigData</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> cacheConfig </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> factory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cacheConfigData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">group</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cacheConfig </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">join</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">","</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> cacheConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMd5</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">valueOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cacheConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLastModifyTime</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        params</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">group</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Lists</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newArrayList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">value</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 组装请求头和请求体</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">HttpHeaders</span><span class="token plain"> headers </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">HttpHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    headers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setContentType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MediaType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APPLICATION_FORM_URLENCODED</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 设置accessToken</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    headers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">X_ACCESS_TOKEN</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">accessTokenManager</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAccessToken</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">HttpEntity</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MultiValueMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> httpEntity </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">HttpEntity</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">params</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> headers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> listenerUrl </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> server </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SHENYU_ADMIN_PATH_CONFIGS_LISTENER</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">JsonArray</span><span class="token plain"> groupJson</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//向admin发起请求，判断组数据是否发生变更</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//这里只是判断了某个组是否发生变更</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">String</span><span class="token plain"> json </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">restTemplate</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">postForEntity</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">listenerUrl</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> httpEntity</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBody</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"listener result: [{}]"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">JsonObject</span><span class="token plain"> responseFromServer </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">json</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">JsonObject</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      groupJson </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> responseFromServer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAsJsonArray</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"data"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RestClientException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">String</span><span class="token plain"> message </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">format</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"listener configs fail, server:[%s], %s"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> server</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 根据发生变更的组，再去获取数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 官网对此处的解释：</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 网关收到响应信息之后，只知道是哪个 Group 发生了配置变更，还需要再次请求该 Group 的配置数据。</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 这里可能会存在一个疑问：为什么不是直接将变更的数据写出？</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 我们在开发的时候，也深入讨论过该问题，因为 http 长轮询机制只能保证准实时，如果在网关层处理不及时，</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 或者管理员频繁更新配置，很有可能便错过了某个配置变更的推送，安全起见，我们只告知某个 Group 信息发生了变更。</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 个人理解：</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 如果将变更数据直接写出，当管理员频繁更新配置时，第一次更新了，将client移除阻塞队列，返回响应信息给网关。</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 如果这个时候进行了第二次更新，那么当前的client是不在阻塞队列中，所以这一次的变更就会错过。</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 网关层处理不及时，也是同理。</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 这是一个长轮询，一个网关一个同步线程，可能存在耗时的过程。</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 如果admin有数据变更，当前网关client是没有在阻塞队列中，就不到数据。</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">groupJson</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> groupJson</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// fetch group configuration async.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> changedGroups </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">groupJson</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Group config changed: {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Arrays</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changedGroups</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doFetchGroupConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">server</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> changedGroups</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>这里需要特别解释一点的是：在长轮询任务中，为什么不直接拿到变更的数据？而是先判断哪个分组数据发生了变更，然后再次请求<code>admin</code>，获取变更数据？</p>
<p>官网对此处的解释是：</p>
<blockquote>
<p>网关收到响应信息之后，只知道是哪个 Group 发生了配置变更，还需要再次请求该 Group 的配置数据。
这里可能会存在一个疑问：为什么不是直接将变更的数据写出？
我们在开发的时候，也深入讨论过该问题，因为 <code>http</code> 长轮询机制只能保证准实时，如果在网关层处理不及时，
或者管理员频繁更新配置，很有可能便错过了某个配置变更的推送，安全起见，我们只告知某个 Group 信息发生了变更。</p>
</blockquote>
<p>个人理解是：</p>
<blockquote>
<p>如果将变更数据直接写出，管理员频繁更新配置时，第一次更新了，将<code>client</code>移除阻塞队列，返回响应信息给网关。如果这个时候进行了第二次更新，那么当前的<code>client</code>是不在阻塞队列中，所以这一次的变更就会错过。网关层处理不及时，也是同理。 这是一个长轮询，一个网关一个同步线程，可能存在耗时的过程。如果<code>admin</code>有数据变更，当前网关client是没有在阻塞队列中，就会更新不到数据。</p>
</blockquote>
<p>我们还没有分析到<code>admin</code>端的处理逻辑，先大概说一下。在<code>admin</code>端，会将网关<code>client</code>放到阻塞队列，有数据变更，网关<code>client</code>就会出队列，发送变更数据。所以，如果有数据变更时，网关<code>client</code>不在阻塞队列，那么就无法得到当前变更的数据。</p>
<p>知道哪个分组数据发生变更时，主动再向<code>admin</code>获取变更的数据，根据分组不同，全量拿数据。调用方法是<code>doFetchGroupConfig()</code>，这个在前面已经分析过了。</p>
<p>分析到这里，网关端的数据同步操作就完成了。长轮询任务就是不断向<code>admin</code>发起请求，看看数据是否发生变更，如果有分组数据发生变更，那么就再主动向<code>admin</code>发起请求，获取变更数据，然后更新网关内存中的数据。</p>
<p>网关端长轮询任务流程：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/http-long-polling-sequence-zh-9d03d97d038b1f3348c31b9eb0133086.png" width="2205" height="883" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-admin数据同步">3. admin数据同步<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#3-admin%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>从前面分析的过程中，可以看到，网关端主要调用<code>admin</code>的两个接口：</p>
<ul>
<li class=""><code>/configs/listener</code>：判断组数据是否发生变更；</li>
<li class=""><code>/configs/fetch</code>：获取变更组数据。</li>
</ul>
<p>直接从这两个接口分析的话，可能有的地方不好理解，所以我们还是从<code>admin</code>启动流程开始分析数据同步过程。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="31-加载配置">3.1 加载配置<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#31-%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>如果在配置文件<code>application.yml</code>中，进行了如下配置，就表示通过<code>http长轮询</code>的方式进行数据同步。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">sync</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><br></span></code></pre></div></div>
<p>程序启动时，通过<code>springboot</code>条件装配实现数据同步类的配置加载。在这个过程中，会创建<code>HttpLongPollingDataChangedListener</code>，负责处理长轮询的相关实现逻辑。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 数据同步配置类</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 通过springboot条件装配实现</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type Data sync configuration.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataSyncConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * http长轮询</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * http long polling.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.sync.http.enabled"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> havingValue </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"true"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@EnableConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpSyncProperties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpLongPollingListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnMissingBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpLongPollingDataChangedListener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">HttpLongPollingDataChangedListener</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">httpLongPollingDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpSyncProperties</span><span class="token plain"> httpSyncProperties</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">HttpLongPollingDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">httpSyncProperties</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="32-数据变更监听器实例化">3.2 数据变更监听器实例化<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#32-%E6%95%B0%E6%8D%AE%E5%8F%98%E6%9B%B4%E7%9B%91%E5%90%AC%E5%99%A8%E5%AE%9E%E4%BE%8B%E5%8C%96" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">HttpLongPollingDataChangedListener</li>
</ul>
<p>数据变更监听器通过构造函数的方式完成实例化和初始化操作。在构造函数中会创建阻塞队列，用于存放客户端；创建线程池，用于执行延迟任务，周期任务；保存长轮询相关属性信息。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">HttpLongPollingDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpSyncProperties</span><span class="token plain"> httpSyncProperties</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 默认客户端（这里是网关）1024个</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">clients </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ArrayBlockingQueue</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1024</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 创建线程池</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// ScheduledThreadPoolExecutor 可以执行延迟任务，周期任务，普通任务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">scheduler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ScheduledThreadPoolExecutor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">ShenyuThreadFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"long-polling"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 长轮询的属性信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">httpSyncProperties </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> httpSyncProperties</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>另外，它的类图关系如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/data-changed-listener-1c8e4c0f4279cdb33b27c52cc933cac5.png" width="857" height="457" class="img_ev3q"></p>
<p>实现了<code>InitializingBean</code>接口，所以在<code>bean</code>的初始化过程中执行<code>afterInitialize()</code>方法。通过线程池执行周期任务：更新内存中<code>（CACHE）</code>的数据每隔<code>5</code>分钟执行一次，<code>5</code>分钟后开始执行。刷新本地缓存就是从数据库读取数据到本地缓存（这里就是内存），通过<code>refreshLocalCache()</code>完成。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpLongPollingDataChangedListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractDataChangedListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * 在 InitializingBean接口中的afterPropertiesSet()方法中被调用，即在bean的初始化过程中执行</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">afterInitialize</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> syncInterval </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> httpSyncProperties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRefreshInterval</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toMillis</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 执行周期任务：更新内存中（CACHE）的数据每隔5分钟执行一次，5分钟后开始执行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 防止admin先启动一段时间后，产生了数据；然后网关初次连接时，没有拿到全量数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    scheduler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">scheduleWithFixedDelay</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"http sync strategy refresh config start."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 从数据库读取数据到本地缓存（这里就是内存）</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">refreshLocalCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"http sync strategy refresh config success."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Exception</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"http sync strategy refresh config error!"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> syncInterval</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> syncInterval</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">MILLISECONDS</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"http sync strategy refresh interval: {}ms"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> syncInterval</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">refreshLocalCache()</li>
</ul>
<p>分别对5种数据类型进行更新。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractDataChangedListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">DataChangedListener</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 从数据库读取数据到本地缓存（这里就是内存）</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">refreshLocalCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//更新认证数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateAppAuthCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//更新插件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updatePluginCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//更新规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateRuleCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//更新选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateSelectorCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//更新元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateMetaDataCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>5个更新方法的逻辑是类似的，调用<code>service</code>方法获取数据，然后放到内存<code>CACHE</code>中。以更新规则数据方法<code>updateRuleCache()</code>为例，传入规则枚举类型，调用<code>ruleService.listAll()</code>从数据库获取所有规则数据。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Update rule cache.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">updateRuleCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RULE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">updateCache()</li>
</ul>
<p>使用数据库中的数据更新内存中的数据。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractDataChangedListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">DataChangedListener</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 缓存数据的 Map</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConcurrentMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">ConfigDataCache</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">CACHE</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ConcurrentHashMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * if md5 is not the same as the original, then update lcoal cache.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * 更新缓存中的数据</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param group ConfigGroupEnum</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param &lt;T&gt; the type of class</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param data the new config data</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">updateCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigGroupEnum</span><span class="token plain"> group</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//数据序列化</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> json </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//传入md5值和修改时间</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ConfigDataCache</span><span class="token plain"> newVal </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ConfigDataCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">group</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Md5Utils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">md5</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">System</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">currentTimeMillis</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//更新分组数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ConfigDataCache</span><span class="token plain"> oldVal </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">CACHE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newVal</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> newVal</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"update config cache[{}], old: {}, updated: {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> group</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> oldVal</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> newVal</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>初始化的过程就是启动周期性任务，定时从数据库获取数据更新内存数据。</p>
<p>接下来开始对两个接口开始分析：</p>
<ul>
<li class=""><code>/configs/listener</code>：判断组数据是否发生变更；</li>
<li class=""><code>/configs/fetch</code>：获取变更组数据。</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="33--数据变更轮询接口">3.3  数据变更轮询接口<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#33--%E6%95%B0%E6%8D%AE%E5%8F%98%E6%9B%B4%E8%BD%AE%E8%AF%A2%E6%8E%A5%E5%8F%A3" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class=""><code>/configs/listener</code>：判断组数据是否发生变更；</li>
</ul>
<p>接口类是<code>ConfigController</code>，只有使用<code>http长轮询</code>进行数据同步时才会生效。接口方法<code>listener()</code>没有其他逻辑，直接调用<code>doLongPolling()</code>方法。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">   </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * This Controller only when HttpLongPollingDataChangedListener exist, will take effect.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpLongPollingDataChangedListener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RestController</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequestMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/configs"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ConfigController</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpLongPollingDataChangedListener</span><span class="token plain"> longPollingListener</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ConfigController</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpLongPollingDataChangedListener</span><span class="token plain"> longPollingListener</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">longPollingListener </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> longPollingListener</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 省略其他逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Listener.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 监听数据变更，执行长轮询</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param request  the request</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param response the response</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@PostMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/listener"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">listener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpServletRequest</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpServletResponse</span><span class="token plain"> response</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        longPollingListener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doLongPolling</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">HttpLongPollingDataChangedListener#doLongPolling()</li>
</ul>
<p>执行长轮询任务：如果有数据变更，将会立即响应给客户端（这里就是网关端）。否则，客户端会一直被阻塞，直到有数据变更或者超时。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpLongPollingDataChangedListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractDataChangedListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * 执行长轮询：如果有数据变更，会立即响应给客户端（这里就是网关端）。</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * 否则，否则客户端会一直被阻塞，直到有数据变更或者超时。</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param request</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param response</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doLongPolling</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpServletRequest</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpServletResponse</span><span class="token plain"> response</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// compare group md5</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 比较md5，判断网关的数据和admin端的数据是否一致，得到发生变更的数据组</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConfigGroupEnum</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changedGroup </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">compareChangedGroup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> clientIp </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getRemoteIp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// response immediately.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 有变更的数据，则立即向网关响应</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changedGroup</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">generateResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">response</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> changedGroup</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token class-name">Log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"send response with the changed group, ip={}, group={}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> clientIp</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> changedGroup</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 没有变更，则将客户端（这里就是网关）放进阻塞队列</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">AsyncContext</span><span class="token plain"> asyncContext </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">startAsync</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    asyncContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0L</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    scheduler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">LongPollingClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">asyncContext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> clientIp</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">HttpConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SERVER_MAX_HOLD_TIMEOUT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">HttpLongPollingDataChangedListener#compareChangedGroup()</li>
</ul>
<p>判断组数据是否发生变更，判断逻辑是比较网关端和<code>admin</code>端的<code>md5</code>值和<code>lastModifyTime</code>。</p>
<ul>
<li class="">如果<code>md5</code>值不一样，那么需要更新；</li>
<li class="">如果<code>admin</code>端的<code>lastModifyTime</code>大于网关端的<code>lastModifyTime</code>，那么需要更新。</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 判断组数据是否发生变更</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param request</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConfigGroupEnum</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">compareChangedGroup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpServletRequest</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConfigGroupEnum</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changedGroup </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ArrayList</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">values</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">length</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token plain"> group </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">values</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 网关端数据的md5值和lastModifyTime</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> params </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">split</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getParameter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">group</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token char">','</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">params </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> params</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">length </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"group param invalid:"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getParameter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">group</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">String</span><span class="token plain"> clientMd5 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> params</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> clientModifyTime </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">NumberUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toLong</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">params</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ConfigDataCache</span><span class="token plain"> serverCache </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">CACHE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">group</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// do check. 判断组数据是否发生变更</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">checkCacheDelayAndUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serverCache</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> clientMd5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> clientModifyTime</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                changedGroup</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">group</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> changedGroup</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">LongPollingClient</li>
</ul>
<p>没有变更数据，则将客户端（这里就是网关）放进阻塞队列。阻塞时间是60秒，即60秒后移除，并响应客户端。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">LongPollingClient</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">Runnable</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 省略了其他逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 先设置定时任务：60秒后移除，并响应客户端</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">asyncTimeoutFuture </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> scheduler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">schedule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    clients</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">remove</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">LongPollingClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConfigGroupEnum</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changedGroups </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">compareChangedGroup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpServletRequest</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> asyncContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token function" style="color:#d73a49">sendResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changedGroups</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> timeoutTime</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">MILLISECONDS</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 添加到阻塞队列</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                clients</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Exception</span><span class="token plain"> ex</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"add long polling client error"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ex</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Send response.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param changedGroups the changed groups</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sendResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConfigGroupEnum</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changedGroups</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// cancel scheduler</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> asyncTimeoutFuture</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                asyncTimeoutFuture</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cancel</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 响应变更的组</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">generateResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpServletResponse</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> asyncContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> changedGroups</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            asyncContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">complete</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="34--获取变更数据接口">3.4  获取变更数据接口<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#34--%E8%8E%B7%E5%8F%96%E5%8F%98%E6%9B%B4%E6%95%B0%E6%8D%AE%E6%8E%A5%E5%8F%A3" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class=""><code>/configs/fetch</code>：获取变更数据；</li>
</ul>
<p>根据网关传入的参数，获取分组数据，返回结果。主要实现方法是<code>longPollingListener.fetchConfig()</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpLongPollingDataChangedListener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RestController</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequestMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/configs"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ConfigController</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpLongPollingDataChangedListener</span><span class="token plain"> longPollingListener</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ConfigController</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpLongPollingDataChangedListener</span><span class="token plain"> longPollingListener</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">longPollingListener </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> longPollingListener</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Fetch configs shenyu result.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 全量获取分组数据</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param groupKeys the group keys</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the shenyu result</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@GetMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/fetch"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuAdminResult</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">fetchConfigs</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@NotNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> groupKeys</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">ConfigData</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Maps</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newHashMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> groupKey </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> groupKeys</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ConfigData</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> data </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> longPollingListener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fetchConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">valueOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">groupKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">groupKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuAdminResult</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">success</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 省略了其他接口</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">AbstractDataChangedListener#fetchConfig()</li>
</ul>
<p>数据获取直接从<code>CACHE</code>中拿，然后根据不同分组类型进行匹配，封装。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractDataChangedListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">DataChangedListener</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * fetch configuration from cache.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * 获取分组下的全量数据</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @param groupKey the group key</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   * @return the configuration data</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">   */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ConfigData</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">fetchConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigGroupEnum</span><span class="token plain"> groupKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 直接从 CACHE 中拿数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ConfigDataCache</span><span class="token plain"> config </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">CACHE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">groupKey</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">groupKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">APP_AUTH</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 认证数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildConfigData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">config</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">AppAuthData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 插件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildConfigData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">config</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">RULE</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildConfigData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">config</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildConfigData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">config</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildConfigData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">config</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">MetaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">default</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 其他类型，抛出异常</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">IllegalStateException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Unexpected groupKey: "</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> groupKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="35-数据变更">3.5 数据变更<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#35-%E6%95%B0%E6%8D%AE%E5%8F%98%E6%9B%B4" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>在之前的<code>websocket</code>数据同步和<code>zookeeper</code>数据同步源码分析文章中，我们知道<code>admin</code>端数据同步设计结构如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/data-changed-listener-admin-2f384e703652e9e28db8447b1cbdaea7.png" width="1868" height="433" class="img_ev3q"></p>
<p>各种数据变更监听器都是<code>DataChangedListener</code>的子类。</p>
<p>当在<code>admin</code>端修改数据后，通过<code>Spring</code>的事件处理机制，发送事件通知。发送逻辑如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Event forwarders, which forward the changed events to each ConfigEventListener.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 数据变更事件分发器：当admin端有数据发生变更时，将变更数据同步到 ShenYu 网关</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 数据变更依赖于Spring的事件监听机制：ApplicationEventPublisher --&gt; ApplicationEvent --&gt; ApplicationListener</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEventDispatcher</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataChangedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">//省略了其他逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 有数据变更时，调用此方法</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param event</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"unchecked"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历数据变更监听器(一般使用一种数据同步的方式就好了)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataChangedListener</span><span class="token plain"> listener </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> listeners</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 哪种数据发生变更</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">APP_AUTH</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 认证信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onAppAuthChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AppAuthData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 插件信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onPluginChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">RULE</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onRuleChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 当选择器数据更新时，更新API文档信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    applicationContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">LoadServiceDocEntry</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">loadDocOnSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onMetaDataChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">default</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 其他类型，抛出异常</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">IllegalStateException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Unexpected value: "</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>假设，对插件信息进行了修改，通过<code>http长轮询</code>的方式进行数据同步，那么<code>listener.onPluginChanged()</code>的实际调用的是<code>org.apache.shenyu.admin.listener.AbstractDataChangedListener#onPluginChanged</code>：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 在admin的操作，有插件发生了更新</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param changed   the changed</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param eventType the event type</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onPluginChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changed</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 更新内存CACHE</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updatePluginCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 执行变更任务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">afterPluginChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>有两个处理操作，一是更新内存<code>CACHE</code>，这个在前面分析过了；另一个是执行变更任务，在线程池中执行。</p>
<ul>
<li class="">HttpLongPollingDataChangedListener#afterPluginChanged()</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">afterPluginChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 在线程池中执行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        scheduler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangeTask</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">DataChangeTask</li>
</ul>
<p>数据变更任务：将阻塞队列中的客户端依次移除，并发送响应，通知网关有组数据发生变更。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangeTask</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">Runnable</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token comment" style="color:#999988;font-style:italic">//省略了其他逻辑 </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 阻塞队列中的客户端超过了给定的值100，则分批执行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clients</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> httpSyncProperties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getNotifyBatchSize</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">LongPollingClient</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> targetClients </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ArrayList</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clients</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                clients</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">drainTo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">targetClients</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">LongPollingClient</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> partitionClients </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Lists</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">partition</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">targetClients</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> httpSyncProperties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getNotifyBatchSize</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">               </span><span class="token comment" style="color:#999988;font-style:italic">// 分批执行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                partitionClients</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">item </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> scheduler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doRun</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">item</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 执行任务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token function" style="color:#d73a49">doRun</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clients</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doRun</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">LongPollingClient</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> clients</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 通知所有客户端发生了数据变更</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Iterator</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">LongPollingClient</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> iter </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> clients</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">iterator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> iter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">hasNext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">LongPollingClient</span><span class="token plain"> client </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> iter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">next</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                iter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">remove</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 发送响应</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sendResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">groupKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"send response with the changed group,ip={}, group={}, changeTime={}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ip</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> groupKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> changeTime</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>至此，<code>admin</code>端数据同步逻辑就分析完了。在基于<code>http长轮询</code>数据同步是，它主要有三个功能：</p>
<ul>
<li class="">提供数据变更监听接口；</li>
<li class="">提供获取变更数据接口；</li>
<li class="">有数据变更时，移除阻塞队列中的客户端，并响应结果。</li>
</ul>
<p>最后，用三张图描述下<code>admin</code>端长轮询任务流程：</p>
<ul>
<li class=""><code>/configs/listener</code>数据变更监听接口：</li>
</ul>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/http-long-polling-listener-zh-a0458f05d312cb977f000662b3791567.png" width="1265" height="796" class="img_ev3q"></p>
<ul>
<li class=""><code>/configs/fetch</code>获取变更数据接口：</li>
</ul>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/http-long-polling-fetch-zh-59963a9119cc79d08e95aa5f4442f413.png" width="969" height="612" class="img_ev3q"></p>
<ul>
<li class="">在admin后台管理系统更新数据，进行数据同步：</li>
</ul>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/http-long-polling-admin-update-zh-97645cfabead723acf9243cfae2d2dbc.png" width="2387" height="771" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-总结">4. 总结<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Http-Data-Sync#4-%E6%80%BB%E7%BB%93" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>本文主要对<code>ShenYu</code>网关中的<code>http长轮询</code>数据同步进行了源码分析。涉及到的主要知识点如下：</p>
<ul>
<li class=""><code>http长轮询</code>由网关端主动发起请求，不断请求<code>admin</code>端；</li>
<li class="">变更数据以组为粒度（认证信息、插件、选择器、规则、元数据）；</li>
<li class=""><code>http长轮询</code>结果只拿到了变更组，还需要再次发起请求获取组数据；</li>
<li class="">数据是否更新由<code>md5</code>值和修改时间<code>lastModifyTime</code>决定。</li>
</ul>]]></content>
        <author>
            <name>midnight2104</name>
            <uri>https://github.com/midnight2104</uri>
        </author>
        <category label="http" term="http"/>
        <category label="data sync" term="data sync"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Nacos数据同步源码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync</id>
        <link href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[Apache ShenYu 是一个异步的，高性能的，跨语言的，响应式的 API 网关。]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p><a href="https://shenyu.apache.org/zh/docs/index" target="_blank" rel="noopener noreferrer" class="">Apache ShenYu</a> 是一个异步的，高性能的，跨语言的，响应式的 <code>API</code> 网关。</p>
</blockquote>
<p>在<code>ShenYu</code>网关中，数据同步是指，当在后台管理系统中，数据发送了更新后，如何将更新的数据同步到网关中。<code>Apache ShenYu</code> 网关当前支持<code>ZooKeeper</code>、<code>WebSocket</code>、<code>Http长轮询</code>、<code>Nacos</code> 、<code>Etcd</code> 和 <code>Consul</code> 进行数据同步。本文的主要内容是基于<code>Nacos</code>的数据同步源码分析。</p>
<blockquote>
<p>本文基于<code>shenyu-2.4.0</code>版本进行源码分析，官网的介绍请参考 <a href="https://shenyu.apache.org/zh/docs/design/data-sync" target="_blank" rel="noopener noreferrer" class="">数据同步原理</a> 。</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-关于nacos">1. 关于Nacos<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync#1-%E5%85%B3%E4%BA%8Enacos" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p><a href="https://github.com/alibaba/nacos" target="_blank" rel="noopener noreferrer" class=""><code>Nacos</code></a> 平台用于动态服务发现，以及配置和服务管理。 <code>Shenyu</code>网关可选择使用<code>Nacos</code>进行数据同步。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-admin数据同步">2. Admin数据同步<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync#2-admin%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>我们从一个实际案例进行源码追踪，比如在后台管理系统中，对<code>Divide</code>插件中的一条选择器数据进行更新，将权重更新为90：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/update-selector-zh-1f49b39fb8e5ce2c26a80018669619ea.png" width="2385" height="1185" class="img_ev3q"></p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="21-接收数据">2.1 接收数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync#21-%E6%8E%A5%E6%94%B6%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">SelectorController.updateSelector()</li>
</ul>
<p>进入<code>SelectorController</code>类中的<code>updateSelector()</code>方法，它负责数据的校验，添加或更新数据，返回结果信息。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Validated</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequiredArgsConstructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RestController</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequestMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/selector"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SelectorController</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@PutMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/{id}"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuAdminResult</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">updateSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@PathVariable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"id"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@Valid</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@RequestBody</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 设置当前选择器数据id</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 创建或更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Integer</span><span class="token plain"> updateCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createOrUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 返回结果信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuAdminResult</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">success</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE_SUCCESS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> updateCount</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="22-处理数据">2.2 处理数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync#22-%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">SelectorServiceImpl.createOrUpdate()</li>
</ul>
<p>在<code>SelectorServiceImpl</code>类中通过<code>createOrUpdate()</code>方法完成数据的转换，保存到数据库，发布事件，更新<code>upstream</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@RequiredArgsConstructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SelectorServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SelectorService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 负责事件发布的eventPublisher</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApplicationEventPublisher</span><span class="token plain"> eventPublisher</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Transactional</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rollbackFor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createOrUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> selectorCount</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建数据 DTO --&gt; DO</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SelectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorConditionDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorConditionDTOs </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSelectorConditions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 判断是添加还是更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插入选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插入选择器中的条件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setSelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorConditionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorConditionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// check selector add</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 权限检查</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataPermissionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listByUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">JwtUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserInfo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">DataPermissionDTO</span><span class="token plain"> dataPermissionDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataPermissionDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">JwtUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserInfo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setDataId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setDataType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">AdminConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR_DATA_TYPE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataPermissionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildPermissionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 更新数据，先删除再新增</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//delete rule condition then add</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">deleteByQuery</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">SelectorConditionQuery</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setSelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">SelectorConditionDO</span><span class="token plain"> selectorConditionDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SelectorConditionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorConditionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发布事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 更新upstream</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">updateDivideUpstream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> selectorCount</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>在<code>Service</code>类完成数据的持久化操作，即保存数据到数据库，这个比较简单，就不深入追踪了。关于更新<code>upstream</code>操作，放到后面对应的章节中进行分析，重点关注发布事件的操作，它会执行数据同步。</p>
<p><code>publishEvent()</code>方法的逻辑是：找到选择器对应的插件，构建条件数据，发布变更数据。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorConditionDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 找到选择器对应的插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PluginDO</span><span class="token plain"> pluginDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pluginMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selectById</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建条件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConditionData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> conditionDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain">                selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConditionTransfer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">mapToSelectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发布变更数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">transFrom</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> conditionDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>发布变更数据通过<code>eventPublisher.publishEvent()</code>完成，这个<code>eventPublisher</code>对象是一个<code>ApplicationEventPublisher</code>类，这个类的全限定名是<code>org.springframework.context.ApplicationEventPublisher</code>。看到这儿，我们知道了发布数据是通过<code>Spring</code>相关的功能来完成的。</p>
<blockquote>
<p>关于<code>ApplicationEventPublisher</code>：</p>
<p>当有状态发生变化时，发布者调用 <code>ApplicationEventPublisher</code> 的 <code>publishEvent</code> 方法发布一个事件，<code>Spring</code>容器广播事件给所有观察者，调用观察者的 <code>onApplicationEvent</code> 方法把事件对象传递给观察者。调用 <code>publishEvent</code>方法有两种途径，一种是实现接口由容器注入 <code>ApplicationEventPublisher</code> 对象然后调用其方法，另一种是直接调用容器的方法，两种方法发布事件没有太大区别。</p>
<ul>
<li class=""><code>ApplicationEventPublisher</code>：发布事件；</li>
<li class=""><code>ApplicationEvent</code>：<code>Spring</code> 事件，记录事件源、时间和数据；</li>
<li class=""><code>ApplicationListener</code>：事件监听者，观察者；</li>
</ul>
</blockquote>
<p>在<code>Spring</code>的事件发布机制中，有三个对象，</p>
<p>一个是发布事件的<code>ApplicationEventPublisher</code>，在<code>ShenYu</code>中通过构造器注入了一个<code>eventPublisher</code>。</p>
<p>另一个对象是<code>ApplicationEvent</code>，在<code>ShenYu</code>中通过<code>DataChangedEvent</code>继承了它，表示事件对象。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">ApplicationEvent</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>最后一个是 <code>ApplicationListener</code>，在<code>ShenYu</code>中通过<code>DataChangedEventDispatcher</code>类实现了该接口，作为事件的监听者，负责处理事件对象。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEventDispatcher</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataChangedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="23-分发数据">2.3 分发数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync#23-%E5%88%86%E5%8F%91%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">DataChangedEventDispatcher.onApplicationEvent()</li>
</ul>
<p>当事件发布完成后，会自动进入到<code>DataChangedEventDispatcher</code>类中的<code>onApplicationEvent()</code>方法，进行事件处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEventDispatcher</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataChangedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 有数据变更时，调用此方法</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param event</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"unchecked"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历数据变更监听器(一般使用一种数据同步的方式就好了)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataChangedListener</span><span class="token plain"> listener </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> listeners</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 哪种数据发生变更</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">APP_AUTH</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 认证信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onAppAuthChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AppAuthData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 插件信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onPluginChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">RULE</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onRuleChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onMetaDataChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">default</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 其他类型，抛出异常</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">IllegalStateException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Unexpected value: "</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>当有数据变更时，调用<code>onApplicationEvent</code>方法，然后遍历所有数据变更监听器，判断是哪种数据类型，交给相应的数据监听器进行处理。</p>
<p><code>ShenYu</code>将所有数据进行了分组，一共是五种：认证信息、插件信息、规则信息、选择器信息和元数据。</p>
<p>这里的数据变更监听器（<code>DataChangedListener</code>），就是数据同步策略的抽象，它的具体实现有：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/data-changed-listener-b01d7410746ca4afd526d8c9df865e9b.png" width="1966" height="482" class="img_ev3q"></p>
<p>这几个实现类就是当前<code>ShenYu</code>支持的同步策略：</p>
<ul>
<li class=""><code>WebsocketDataChangedListener</code>：基于<code>websocket</code>的数据同步；</li>
<li class=""><code>ZookeeperDataChangedListener</code>：基于<code>zookeeper</code>的数据同步；</li>
<li class=""><code>ConsulDataChangedListener</code>：基于<code>consul</code>的数据同步；</li>
<li class=""><code>EtcdDataDataChangedListener</code>：基于<code>etcd</code>的数据同步；</li>
<li class=""><code>HttpLongPollingDataChangedListener</code>：基于<code>http长轮询</code>的数据同步；</li>
<li class=""><code>NacosDataChangedListener</code>：基于<code>nacos</code>的数据同步；</li>
</ul>
<p>既然有这么多种实现策略，那么如何确定使用哪一种呢？</p>
<p>因为本文是基于<code>Nacos</code>的数据同步源码分析，所以这里以<code>NacosDataChangedListener</code>为例，分析它是如何被加载并实现的。</p>
<p>通过查看对<code>NacosDataChangedListener</code>类的调用，可以发现，它是在<code>DataSyncConfiguration</code>类进行配置的。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 数据同步配置类</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 通过springboot条件装配实现</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type Data sync configuration.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataSyncConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">//省略了其他代码......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The type Nacos listener.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.sync.nacos"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"url"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Import</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosConfiguration</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">NacosListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Data changed listener data changed listener.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param configService the config service</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the data changed listener</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnMissingBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosDataChangedListener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">DataChangedListener</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">nacosDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigService</span><span class="token plain"> configService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">NacosDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Nacos data init zookeeper data init.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param configService the config service</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param syncDataService the sync data service</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the nacos data init</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnMissingBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosDataInit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">NacosDataInit</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">nacosDataInit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigService</span><span class="token plain"> configService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">NacosDataInit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">//省略了其他代码......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>这个配置类是通过<code>SpringBoot</code>条件装配类实现的。在<code>NacosListener</code>类上面有几个注解：</p>
<ul>
<li class="">
<p><code>@Configuration</code>：配置文件，应用上下文；</p>
</li>
<li class="">
<p><code>@ConditionalOnProperty(prefix = "shenyu.sync.nacos", name = "url")</code>：属性条件判断，满足条件，该配置类才会生效。也就是说，当我们有如下配置时，就会采用<code>nacos</code>进行数据同步。</p>
<div class="language-properties codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-properties codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key attr-name" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">  sync</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">     nacos</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">          url</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token value attr-value" style="color:#e3116c">localhost:8848</span><br></span></code></pre></div></div>
</li>
<li class="">
<p><code>@Import(NacosConfiguration.class)</code>：导入另一个配置类<code>NacosConfiguration</code>，<code>NacosConfiguration</code>提供了一个方法<code>ConfigService nacosConfigService(final NacosProperties nacosProp)</code>，将Nacos属性转换为<code>ConfigService</code>类型的bean，而Nacos属性是通过<code>@EnableConfigurationProperties(NacosProperties.class)</code> 导入的。我们先看ConfigService类型的bean定义。再分析属性配置类和对应的属性配置文件。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Nacos configuration.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@EnableConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosProperties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">NacosConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * register configService in spring ioc.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param nacosProp the nacos configuration</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return ConfigService {@linkplain ConfigService}</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @throws Exception the exception</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnMissingBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ConfigService</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">nacosConfigService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">NacosProperties</span><span class="token plain"> nacosProp</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Properties</span><span class="token plain"> properties </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Properties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">nacosProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> nacosProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEnabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Use aliyun ACM service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">ENDPOINT</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">NAMESPACE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getNamespace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Use subaccount ACM administrative authority</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">ACCESS_KEY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAccessKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SECRET_KEY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSecretKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SERVER_ADDR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">nacosProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getNamespace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">NAMESPACE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getNamespace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">nacosProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUsername</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">USERNAME</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUsername</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">nacosProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPassword</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PASSWORD</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPassword</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">NacosFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createConfigService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">properties</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>这个方法主要分成两步，第一步根据是否使用了aliyun的ACM服务，从NacosProperties中获取不同的nacos路径和鉴权信息，第二步根据获取到的这些属性，使用Nacos官方的工厂方法，使用反射的方式，创建configService。</p>
<p>接下来，让我们分析一下Nacos的属性配置和对应的配置文件。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type Nacos config.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.sync.nacos"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">NacosProperties</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> namespace</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> username</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> password</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">NacosACMProperties</span><span class="token plain"> acm</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Gets the value of url.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the value of url</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Sets the url.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param url url</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">url </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Gets the value of namespace.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the value of namespace</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getNamespace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> namespace</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Sets the namespace.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param namespace namespace</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setNamespace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> namespace</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">namespace </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> namespace</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Gets the value of username.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the value of username</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getUsername</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> username</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Sets the username.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param username username</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setUsername</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> username</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">username </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> username</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Gets the value of password.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the value of password</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getPassword</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> password</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Sets the password.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param password password</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setPassword</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> password</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">password </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> password</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Gets the value of acm.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the value of acm</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">NacosACMProperties</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> acm</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Sets the acm.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param acm acm</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">NacosACMProperties</span><span class="token plain"> acm</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">acm </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> acm</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">NacosACMProperties</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> enabled</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> endpoint</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> namespace</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> accessKey</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> secretKey</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Gets the value of enabled.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the value of enabled</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">isEnabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> enabled</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Sets the enabled.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param enabled enabled</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setEnabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> enabled</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">enabled </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> enabled</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Gets the value of endpoint.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the value of endpoint</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> endpoint</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Sets the endpoint.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param endpoint endpoint</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> endpoint</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">endpoint </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> endpoint</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Gets the value of namespace.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the value of namespace</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getNamespace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> namespace</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Sets the namespace.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param namespace namespace</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setNamespace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> namespace</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">namespace </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> namespace</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Gets the value of accessKey.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the value of accessKey</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getAccessKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> accessKey</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Sets the accessKey.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param accessKey accessKey</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setAccessKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> accessKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">accessKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> accessKey</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Gets the value of secretKey.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the value of secretKey</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getSecretKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> secretKey</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Sets the secretKey.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param secretKey secretKey</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setSecretKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> secretKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">secretKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> secretKey</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>当我们在配置文件中配置了<code>shenyu.sync.nacos.url</code>属性时，将采用<code>nacos</code>进行数据同步，此时配置类<code>NacosListener</code>会生效，并生成<code>NacosDataChangedListener</code>和<code>NacosDataInit</code>类型的bean。</p>
<ul>
<li class="">生成<code>NacosDataChangedListener</code>类型的bean，<code>nacosDataChangedListener</code>，这个bean将<code>ConfigService</code>类型的bean作为成员变量，<code>ConfigService</code>是nacos官方提供的api，当<code>nacosDataChangedListener</code>监听到事件时，进行回调操作，可以通过该api直接与nacos服务器交互，修改配置。</li>
<li class="">生成<code>NacosDataInit</code>类型的bean，<code>nacosDataInit</code>，这个bean将bean<code>configService</code>和bean<code>syncDataService</code>作为成员变量，调用<code>Nacos</code>的api <code>configService</code>判断配置是否未初始化，未初始化则调用<code>syncDataService</code>进行刷新操作，将在下文详述。
根据上文所述，在事件处理方法<code>onApplicationEvent()</code>中，会触发相应的<code>listener</code>的操作。在我们的案例中，是对一条选择器数据进行更新，数据同步采用的是<code>nacos</code>，所以，代码会进入到<code>NacosDataChangedListener</code>进行选择器数据变更处理。</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//DataChangedEventDispatcher.java</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">		</span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"unchecked"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历数据变更监听器(一般使用一种数据同步的方式就好了)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataChangedListener</span><span class="token plain"> listener </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> listeners</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 哪种数据发生变更</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 省略了其他逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 在我们的案例中，会进入到NacosDataChangedListener进行选择器数据变更处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-nacos数据变更监听器">2.4 Nacos数据变更监听器<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync#24-nacos%E6%95%B0%E6%8D%AE%E5%8F%98%E6%9B%B4%E7%9B%91%E5%90%AC%E5%99%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">
<p>NacosDataChangedListener.onSelectorChanged()</p>
<p>在<code>onSelectorChanged()</code>方法中，判断操作类型，是刷新同步还是更新或创建同步。根据当前选择器数据信息判断节点是否在<code>nacos</code>中。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Use nacos to push data changes.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">NacosDataChangedListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">DataChangedListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息发生改变</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">updateSelectorMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">getConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR_DATA_ID</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                changed</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> ls </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getOrDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ArrayList</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">s </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">s</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sorted</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">SELECTOR_DATA_COMPARATOR</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ls</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">REFRESH</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">MYSELF</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">keySet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">keySet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                changed</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> ls </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getOrDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ArrayList</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sorted</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">SELECTOR_DATA_COMPARATOR</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    ls</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ls</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">default</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                changed</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> ls </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getOrDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ArrayList</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">s </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">s</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sorted</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">SELECTOR_DATA_COMPARATOR</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    ls</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ls</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">publishConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>这部分是核心。<code>changed</code>表示需更新的<code>SelectorData</code>列表，<code>eventType</code>表示事件类型。<code>SELECTOR_MAP</code>的类型是<code>ConcurrentMap&lt;String, List&lt;SelectorData&gt;&gt;</code>，该map的key为selector所属的plugin的名称，value为该plugin下的selector列表。<code>NacosPathConstants.SELECTOR_DATA_ID</code>的值为<code>shenyu.selector.json</code>。操作步骤如下，第一步，使用<code>getConfig</code>方法调用<code>Nacos</code>的api，从<code>Nacos</code>获取<code>group</code>为<code>shenyu.selector.json</code>的配置信息，<code>updateSelectorMap</code>方法使用这些配置信息更新<code>SELECTOR_MAP</code>，这样就同步到了<code>Nacos</code>上最新的selector信息。第二步，再根据事件类型来更新<code>SELECTOR_MAP</code>，最后使用<code>publishConfig</code>方法，调用<code>Nacos</code>的api，将<code>Nacos</code>上，<code>group</code>为<code>shenyu.selector.json</code>的配置进行全量替换。</p>
<p>只要将变动的数据正确写入到<code>Nacos</code>上，<code>admin</code>这边的操作就执行完成了。</p>
<p>在我们当前的案例中，对<code>Divide</code>插件中的一条选择器数据进行更新，将权重更新为90，就会对图中的特定节点更新。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/zookeeper-node-c7628b680a1f1afa0eada97b66fcd5b1.png" width="1704" height="1140" class="img_ev3q"></p>
<p>我们用时序图将上面的更新流程串联起来。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/nacos-sync-sequence-admin-zh-73003e7cb52938c5528bbfcc58adfc17.png" width="1663" height="634" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-网关数据同步">3. 网关数据同步<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync#3-%E7%BD%91%E5%85%B3%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>假设<code>ShenYu</code>网关已经在正常运行，使用的数据同步方式也是<code>nacos</code>。那么当在<code>admin</code>端更新选择器数据后，并且向<code>nacos</code>发送了变更的数据，那网关是如何接收并处理数据的呢？接下来我们就继续进行源码分析，一探究竟。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="31-nacossyncdataservice接收数据">3.1 <code>NacosSyncDataService</code>接收数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync#31-nacossyncdataservice%E6%8E%A5%E6%94%B6%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>网关是通过<code>NacosSyncDataService</code>对<code>nacos</code>进行监听并获取数据更新的，但是在这部分内容之前，我们先看一下<code>NacosSyncDataService</code>类型的bean是如何生成的。答案是在Spring配置类<code>NacosSyncDataConfiguration</code>中定义的。我们看到<code>NacosSyncDataConfiguration</code>类上的注解，<code>@ConditionalOnProperty(prefix = "shenyu.sync.nacos", name = "url")</code>，这个注解我们在上文对<code>ShenYu</code>的Admin端中的<code>NacosListener</code>类进行分析时看到过，是一个属性条件判断，满足条件，该配置类才会生效。也就是说，当我们在<code>Shenyu</code>网关端有如下配置时，就表示<code>Shenyu</code>网关端采用<code>nacos</code>进行数据同步，<code>NacosSyncDataConfiguration</code>这个配置类生效。</p>
<div class="language-properties codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-properties codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key attr-name" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">  sync</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">     nacos</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">          url</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token value attr-value" style="color:#e3116c">localhost:8848</span><br></span></code></pre></div></div>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Nacos sync data configuration for spring boot.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnClass</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosSyncDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.sync.nacos"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"url"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">NacosSyncDataConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Logger</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LOGGER</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">LoggerFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLogger</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosSyncDataConfiguration</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Nacos sync data service.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param configService     the config service</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param pluginSubscriber the plugin subscriber</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param metaSubscribers   the meta subscribers</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param authSubscribers   the auth subscribers</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the sync data service</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">nacosSyncDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConfigService</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> configService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> pluginSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                           </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AuthDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> authSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">LOGGER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"you use nacos sync shenyu data......."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">NacosSyncDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginSubscriber</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                metaSubscribers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collections</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">emptyList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> authSubscribers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collections</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">emptyList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Nacos config service config service.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param nacosConfig the nacos config</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the config service</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @throws Exception the exception</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ConfigService</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">nacosConfigService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">NacosConfig</span><span class="token plain"> nacosConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Properties</span><span class="token plain"> properties </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Properties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">nacosConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> nacosConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEnabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">ENDPOINT</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">NAMESPACE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getNamespace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">ACCESS_KEY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAccessKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SECRET_KEY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAcm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSecretKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SERVER_ADDR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">nacosConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getNamespace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">NAMESPACE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getNamespace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">nacosConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUsername</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">USERNAME</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUsername</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">nacosConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPassword</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                properties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PropertyKeyConst</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PASSWORD</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nacosConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPassword</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">NacosFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createConfigService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">properties</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Http config http config.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the http config</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.sync.nacos"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">NacosConfig</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">nacosConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">NacosConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>我们重点关注一下上面代码中<code>nacosSyncDataService</code>这个bean的生成：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">nacosSyncDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConfigService</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> configService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> pluginSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                           </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AuthDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> authSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">LOGGER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"you use nacos sync shenyu data......."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">NacosSyncDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginSubscriber</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                metaSubscribers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collections</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">emptyList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> authSubscribers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collections</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">emptyList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>是直接调用<code>NacosSyncDataService</code>的构造方法new了一个该类型的对象。我们继续看构造方法：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">NacosSyncDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigService</span><span class="token plain"> configService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginDataSubscriber</span><span class="token plain"> pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AuthDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> authDataSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">super</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> authDataSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">watcherData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">updatePluginMap</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">watcherData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">updateSelectorMap</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">watcherData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RULE_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">updateRuleMap</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">watcherData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">updateMetaDataMap</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">watcherData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">AUTH_DATA_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">updateAuthMap</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">watcherData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> dataId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">OnChange</span><span class="token plain"> oc</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Listener</span><span class="token plain"> listener </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Listener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">receiveConfigInfo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> configInfo</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                oc</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">change</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configInfo</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Executor</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getExecutor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        oc</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">change</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">getConfigAndSignListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> listener</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">LISTENERS</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">computeIfAbsent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> key </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ArrayList</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">listener</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>可以看到，在构造方法中调用了<code>start</code>方法，并且通过<code>watcherData</code>方法创建了监听器，并且关联了回调函数oc，由于我们正在分析selector类型组件的变化，对应的回调函数是<code>updateSelectorMap</code>。这个回调函数用于处理数据。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="32-�处理数据">3.2 处理数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync#32-%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">NacosCacheHandler.updateSelectorMap()</li>
</ul>
<p>经过判空逻辑之后，缓存选择器数据的操作又交给了<code>PluginDataSubscriber</code>处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">updateSelectorMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> configInfo</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toObjectMapList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configInfo</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">values</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flatMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collection</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorDataList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">subscriber </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                subscriber</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unSelectorSubscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                subscriber</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSelectorSubscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">JsonParseException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"sync selector data have error:"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>PluginDataSubscriber</code>是一个接口，它只有一个<code>CommonPluginDataSubscriber</code>实现类，负责处理插件、选择器和规则数据。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="33-通用插件数据订阅者">3.3 通用插件数据订阅者<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync#33-%E9%80%9A%E7%94%A8%E6%8F%92%E4%BB%B6%E6%95%B0%E6%8D%AE%E8%AE%A2%E9%98%85%E8%80%85" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">PluginDataSubscriber.onSelectorSubscribe()</li>
</ul>
<p>它没有其他逻辑，直接调用<code>subscribeDataHandler()</code>方法。在方法中，更具数据类型（插件、选择器或规则），操作类型（更新或删除），去执行不同逻辑。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 通用插件数据订阅者，负责处理所有插件、选择器和规则信息</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type Common plugin data subscriber.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">CommonPluginDataSubscriber</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">PluginDataSubscriber</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">// 处理选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onSelectorSubscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">subscribeDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅数据处理器，处理数据的更新或删除</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">subscribeDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token plain"> classData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> dataType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">classData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">PluginData</span><span class="token plain"> pluginData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cachePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handlerPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 从网关内存移除数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removePlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cacheSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理                    Optional.ofNullable(handlerMap.get(selectorData.getPluginName())).ifPresent(handler -&gt; handler.handlerSelector(selectorData));</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 从网关内存移除数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">RuleData</span><span class="token plain"> ruleData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RuleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cacheRuleData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handlerRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 从网关内存移除数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeRuleData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="34-数据缓存到内存">3.4 数据缓存到内存<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync#34-%E6%95%B0%E6%8D%AE%E7%BC%93%E5%AD%98%E5%88%B0%E5%86%85%E5%AD%98" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>那么更新一条选择器数据，会进入下面的逻辑：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cacheSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理                    </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handlerSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>一是将数据保存到网关的内存中。<code>BaseDataCache</code>是最终缓存数据的类，通过单例模式实现。选择器数据就存到了<code>SELECTOR_MAP</code>这个<code>Map</code>中。在后续使用的时候，也是从这里拿数据。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 私有变量</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  	</span><span class="token comment" style="color:#999988;font-style:italic">// 私有构造器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Gets instance.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *  公开方法</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the instance</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">    *  缓存选择器数据的Map</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * pluginName -&gt; SelectorData.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConcurrentMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Maps</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newConcurrentMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">cacheSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">selectorAccept</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * cache selector data.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 缓存选择器数据</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param data the selector data</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">selectorAccept</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">containsKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作，先删除再插入</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> existList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> resultList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> existList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">r </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">r</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            resultList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> collect </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> resultList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sorted</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Comparator</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comparing</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorData</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">getSort</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> collect</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 新增操作，直接放到Map中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Lists</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newArrayList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>二是如果每个插件还有自己的处理逻辑，那么就去处理。  通过<code>idea</code>编辑器可以看到，当新增一条选择器后，有如下的插件还有处理。这里我们就不再展开了。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/handler-selector-bf05b8fdf80a428aa53606178a42bae6.png" width="2456" height="617" class="img_ev3q"></p>
<p>经过以上的源码追踪，并通过一个实际的案例，在<code>admin</code>端新增更新一条选择器数据，就将<code>nacos</code>数据同步的流程分析清楚了。</p>
<p>我们还是通过时序图将网关端的数据同步流程串联一下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/nacos-sync-sequence-gateway-zh-bdc1404f8b15c4ebb82baaa4485660ac.png" width="957" height="612" class="img_ev3q"></p>
<p>数据同步的流程已经分析完了，为了不让同步流程被打断，在分析过程中就忽略了其他逻辑。网关同步操作初始化的流程在<code>NacosSyncDataService</code>的<code>start</code>方法中，我们在上文分析<code>网关数据同步</code>时分析过了，下面分析<code>Admin</code>的同步数据初始化。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-admin同步数据初始化">4. Admin同步数据初始化<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync#4-admin%E5%90%8C%E6%AD%A5%E6%95%B0%E6%8D%AE%E5%88%9D%E5%A7%8B%E5%8C%96" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p><code>admin</code>端，<code>NacosDataInit</code>类型的bean，在<code>NacosListener</code>中进行定义和生成，如果<code>admin</code>的配置中指定了使用<code>nacos</code>进行数据同步，当<code>admin</code>启动后，会将当前的数据信息全量同步到<code>nacos</code>中，实现逻辑如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type Nacos data init.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">NacosDataInit</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">CommandLineRunner</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Logger</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">LoggerFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLogger</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosDataInit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigService</span><span class="token plain"> configService</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Instantiates a new Nacos data init.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param configService the nacos config service</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param syncDataService the sync data service</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">NacosDataInit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigService</span><span class="token plain"> configService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">configService </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> configService</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">syncDataService </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> args</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> pluginDataId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">NacosPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN_DATA_ID</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> authDataId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">NacosPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">AUTH_DATA_ID</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> metaDataId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">NacosPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA_ID</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">dataIdNotExist</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">dataIdNotExist</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authDataId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">dataIdNotExist</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            syncDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">syncAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">REFRESH</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">dataIdNotExist</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginDataId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">String</span><span class="token plain"> group </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">NacosPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">GROUP</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> timeout </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">NacosPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DEFAULT_TIME_OUT</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> configService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> group</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> timeout</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NacosException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Get data from nacos error."</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>判断<code>nacos</code>中是否存在数据，如果不存在，则进行同步。</p>
<p><code>NacosDataInit</code>实现了<code>CommandLineRunner</code>接口。它是<code>springboot</code>提供的接口，会在所有 <code>Spring Beans</code>初始化之后执行<code>run()</code>方法，常用于项目中初始化的操作。</p>
<ul>
<li class="">SyncDataService.syncAll()</li>
</ul>
<p>从数据库查询数据，然后进行全量数据同步，所有的认证信息、插件信息、选择器信息、规则信息和元数据信息。主要是通过<code>eventPublisher</code>发布同步事件。这里就跟前面提到的同步逻辑就又联系起来了，<code>eventPublisher</code>通过<code>publishEvent()</code>发布完事件后，有<code>ApplicationListener</code>执行事件变更操作，在<code>ShenYu</code>中就是前面提到的<code>DataChangedEventDispatcher</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SyncDataServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 事件发布</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApplicationEventPublisher</span><span class="token plain"> eventPublisher</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">/***</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 全量数据同步</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param type the type</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">syncAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步认证信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        appAuthService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">syncData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步插件信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> pluginDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pluginService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> ruleDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ruleService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RULE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步元数据信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        metaDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">syncData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-总结">5. 总结<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-Nacos-Data-Sync#5-%E6%80%BB%E7%BB%93" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>本文通过一个实际案例，对<code>nacos</code>的数据同步原理进行了源码分析。涉及到的主要知识点如下：</p>
<ul>
<li class="">基于<code>nacos</code>的数据同步，主要是通过<code>watch</code>机制实现；</li>
<li class="">通过<code>Spring</code>完成事件发布和监听；</li>
<li class="">通过抽象<code>DataChangedListener</code>接口，支持多种同步策略，面向接口编程；</li>
<li class="">使用单例设计模式实现缓存数据类<code>BaseDataCache</code>；</li>
<li class="">通过<code>SpringBoot</code>的条件装配和<code>starter</code>加载机制实现配置类的加载。</li>
</ul>]]></content>
        <author>
            <name>4zd</name>
            <uri>https://github.com/4zd</uri>
        </author>
        <category label="nacos" term="nacos"/>
        <category label="data sync" term="data sync"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[WebSocket数据同步源码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync</id>
        <link href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[在ShenYu网关中，数据同步是指，当在后台管理系统中，数据发送了更新后，如何将更新的数据同步到网关中。Apache ShenYu 网关当前支持ZooKeeper、WebSocket、Http长轮询、Nacos 、etcd 和 Consul 进行数据同步。本文的主要内容是基于WebSocket的数据同步源码分析。]]></summary>
        <content type="html"><![CDATA[<p>在<code>ShenYu</code>网关中，数据同步是指，当在后台管理系统中，数据发送了更新后，如何将更新的数据同步到网关中。<code>Apache ShenYu</code> 网关当前支持<code>ZooKeeper</code>、<code>WebSocket</code>、<code>Http长轮询</code>、<code>Nacos</code> 、<code>etcd</code> 和 <code>Consul</code> 进行数据同步。本文的主要内容是基于<code>WebSocket</code>的数据同步源码分析。</p>
<blockquote>
<p>本文基于<code>shenyu-2.4.0</code>版本进行源码分析，官网的介绍请参考 <a href="https://shenyu.apache.org/zh/docs/design/data-sync" target="_blank" rel="noopener noreferrer" class="">数据同步原理</a> 。</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-关于websocket通信">1. 关于WebSocket通信<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#1-%E5%85%B3%E4%BA%8Ewebsocket%E9%80%9A%E4%BF%A1" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p><code>WebSocket</code>协议诞生于<code>2008</code>年，在<code>2011</code>年成为国际标准。它可以双向通信，服务器可以主动向客户端推送信息，客户端也可以主动向服务器发送信息。<code>WebSocket</code>协议建立在 <code>TCP</code> 协议之上，属于应用层，性能开销小，通信高效，协议标识符是<code>ws</code>。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-admin数据同步">2. Admin数据同步<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#2-admin%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>我们从一个实际案例进行源码追踪，比如在后台管理系统中，新增一条选择器数据：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/add-selector-93ff1008c1b0b4627dd3329abc92a7bd.png" width="2481" height="1309" class="img_ev3q"></p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="21-接收数据">2.1 接收数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#21-%E6%8E%A5%E6%94%B6%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">SelectorController.createSelector()</li>
</ul>
<p>进入<code>SelectorController</code>类中的<code>createSelector()</code>方法，它负责数据的校验，添加或更新数据，返回结果信息。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Validated</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequiredArgsConstructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RestController</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequestMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/selector"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SelectorController</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@PostMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuAdminResult</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@Valid</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@RequestBody</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// @Valid 数校验</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 添加或更新数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Integer</span><span class="token plain"> createCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createOrUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 返回结果信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuAdminResult</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">success</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CREATE_SUCCESS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> createCount</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="22-处理数据">2.2 处理数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#22-%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">SelectorServiceImpl.createOrUpdate()</li>
</ul>
<p>在<code>SelectorServiceImpl</code>类中通过<code>createOrUpdate()</code>方法完成数据的转换，保存到数据库，发布事件，更新<code>upstream</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@RequiredArgsConstructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SelectorServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SelectorService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 负责事件发布的eventPublisher</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApplicationEventPublisher</span><span class="token plain"> eventPublisher</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Transactional</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rollbackFor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createOrUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> selectorCount</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建数据 DTO --&gt; DO</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SelectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorConditionDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorConditionDTOs </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSelectorConditions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 判断是添加还是更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插入选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插入选择器中的条件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setSelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorConditionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorConditionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// check selector add</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 权限检查</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataPermissionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listByUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">JwtUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserInfo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">DataPermissionDTO</span><span class="token plain"> dataPermissionDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataPermissionDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">JwtUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserInfo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setDataId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setDataType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">AdminConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR_DATA_TYPE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataPermissionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildPermissionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 更新数据，先删除再新增</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//delete rule condition then add</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">deleteByQuery</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">SelectorConditionQuery</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setSelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">SelectorConditionDO</span><span class="token plain"> selectorConditionDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SelectorConditionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorConditionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发布事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 更新upstream</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">updateDivideUpstream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> selectorCount</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>在<code>Service</code>类完成数据的持久化操作，即保存数据到数据库，这个大家应该很熟悉了，就不展开。关于更新<code>upstream</code>操作，放到后面对应的章节中进行分析，重点关注发布事件的操作，它会进行数据同步。</p>
<p><code>publishEvent()</code>方法的逻辑是：找到选择器对应的插件，构建条件数据，发布变更数据。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">       </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorConditionDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 找到选择器对应的插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PluginDO</span><span class="token plain"> pluginDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pluginMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selectById</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建条件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConditionData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> conditionDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain">                selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConditionTransfer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">mapToSelectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发布变更数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">transFrom</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> conditionDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>发布变更数据通过<code>eventPublisher.publishEvent()</code>完成，这个<code>eventPublisher</code>对象是一个<code>ApplicationEventPublisher</code>类，这个类的全限定名是<code>org.springframework.context.ApplicationEventPublisher</code>。看到这儿，我们知道了发布数据是通过<code>Spring</code>相关的功能来完成的。</p>
<blockquote>
<p>关于<code>ApplicationEventPublisher</code>：</p>
<p>当有状态发生变化时，发布者调用 <code>ApplicationEventPublisher</code> 的 <code>publishEvent</code> 方法发布一个事件，<code>Spring</code>容器广播事件给所有观察者，调用观察者的 <code>onApplicationEvent</code> 方法把事件对象传递给观察者。调用 <code>publishEvent</code>方法有两种途径，一种是实现接口由容器注入 <code>ApplicationEventPublisher</code> 对象然后调用其方法，另一种是直接调用容器的方法，两种方法发布事件没有太大区别。</p>
<ul>
<li class=""><code>ApplicationEventPublisher</code>：发布事件；</li>
<li class=""><code>ApplicationEvent</code>：<code>Spring</code> 事件，记录事件源、时间和数据；</li>
<li class=""><code>ApplicationListener</code>：事件监听者，观察者。</li>
</ul>
</blockquote>
<p>在<code>Spring</code>的事件发布机制中，有三个对象，</p>
<p>一个是发布事件的<code>ApplicationEventPublisher</code>，在<code>ShenYu</code>中通过构造器注入了一个<code>eventPublisher</code>。</p>
<p>另一个对象是<code>ApplicationEvent</code>，在<code>ShenYu</code>中通过<code>DataChangedEvent</code>继承了它，表示事件对象。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">ApplicationEvent</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>最后一个是 <code>ApplicationListener</code>，在<code>ShenYu</code>中通过<code>DataChangedEventDispatcher</code>类实现了该接口，作为事件的监听者，负责处理事件对象。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEventDispatcher</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataChangedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="23-分发数据">2.3 分发数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#23-%E5%88%86%E5%8F%91%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">DataChangedEventDispatcher.onApplicationEvent()</li>
</ul>
<p>当事件发布完成后，会自动进入到<code>DataChangedEventDispatcher</code>类中的<code>onApplicationEvent()</code>方法，进行事件处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEventDispatcher</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataChangedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 有数据变更时，调用此方法</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param event</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"unchecked"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历数据变更监听器(一般使用一种数据同步的方式就好了)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataChangedListener</span><span class="token plain"> listener </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> listeners</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 哪种数据发生变更</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">APP_AUTH</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 认证信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onAppAuthChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AppAuthData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 插件信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onPluginChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">RULE</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onRuleChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onMetaDataChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">default</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 其他类型，抛出异常</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">IllegalStateException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Unexpected value: "</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>当有数据变更时，调用<code>onApplicationEvent</code>方法，然后遍历所有数据变更监听器，判断是哪种数据类型，交给相应的数据监听器进行处理。</p>
<p><code>ShenYu</code>将所有数据进行了分组，一共是五种：认证信息、插件信息、规则信息、选择器信息和元数据。</p>
<p>这里的数据变更监听器（<code>DataChangedListener</code>），就是数据同步策略的抽象，它的具体实现有：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/data-changed-listener-b01d7410746ca4afd526d8c9df865e9b.png" width="1966" height="482" class="img_ev3q"></p>
<p>这几个实现类就是当前<code>ShenYu</code>支持的同步策略：</p>
<ul>
<li class=""><code>WebsocketDataChangedListener</code>：基于<code>websocket</code>的数据同步；</li>
<li class=""><code>ZookeeperDataChangedListener</code>：基于<code>zookeeper</code>的数据同步；</li>
<li class=""><code>ConsulDataChangedListener</code>：基于<code>consul</code>的数据同步；</li>
<li class=""><code>EtcdDataDataChangedListener</code>：基于<code>etcd</code>的数据同步；</li>
<li class=""><code>HttpLongPollingDataChangedListener</code>：基于<code>http长轮询</code>的数据同步；</li>
<li class=""><code>NacosDataChangedListener</code>：基于<code>nacos</code>的数据同步；</li>
</ul>
<p>既然有这么多种实现策略，那么如何确定使用哪一种呢？</p>
<p>因为本文是基于<code>websocket</code>的数据同步源码分析，所以这里以<code>WebsocketDataChangedListener</code>为例，分析它是如何被加载并实现的。</p>
<p>通过在源码工程中进行全局搜索，可以看到，它的实现是在<code>DataSyncConfiguration</code>类完成的。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 数据同步配置类</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 通过springboot条件装配实现</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type Data sync configuration.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataSyncConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * websocket数据同步（默认策略）</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The WebsocketListener(default strategy).</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.sync.websocket.enabled"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> havingValue </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"true"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> matchIfMissing </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@EnableConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">WebsocketSyncProperties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">WebsocketListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Config event listener data changed listener.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * 配置websocket数据变更监听器</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the data changed listener</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnMissingBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">WebsocketDataChangedListener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">DataChangedListener</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">websocketDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">WebsocketDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Websocket collector.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Websocket处理类：建立连接，发送消息，关闭连接等操作</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the websocket collector</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnMissingBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">WebsocketCollector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">WebsocketCollector</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">websocketCollector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">WebsocketCollector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Server endpoint exporter </span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the server endpoint exporter</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnMissingBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ServerEndpointExporter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ServerEndpointExporter</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">serverEndpointExporter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ServerEndpointExporter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>这个配置类是通过<code>SpringBoot</code>条件装配类实现的。在<code>WebsocketListener</code>类上面有几个注解：</p>
<ul>
<li class="">
<p><code>@Configuration</code>：配置文件，应用上下文；</p>
</li>
<li class="">
<p><code>@ConditionalOnProperty(name = "shenyu.sync.websocket.enabled", havingValue = "true", matchIfMissing = true)</code>：属性条件判断，满足条件，该配置类才会生效。也就是说，当我们有如下配置时，就会采用<code>websocket</code>进行数据同步。不过，这里需要注意下<code>matchIfMissing = true</code>这个属性，它表示，如果你没有如下的配置，该配置类也会生效。基于<code>websocket</code>的数据同步时官方推荐的方式，也是默认采用的方式。</p>
<div class="language-properties codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-properties codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key attr-name" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">  sync</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">    websocket</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">      enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token value attr-value" style="color:#e3116c">true</span><br></span></code></pre></div></div>
</li>
<li class="">
<p><code>@EnableConfigurationProperties</code>：启用配置属性；</p>
</li>
</ul>
<p>当我们主动配置，采用<code>websocket</code>进行数据同步时，<code>WebsocketDataChangedListener</code>就会生成。所以在事件处理方法<code>onApplicationEvent()</code>中，就会到相应的<code>listener</code>中。在我们的案例中，是新增加了一条选择器数据，数据通过采用的是<code>websocket</code>，所以，代码会进入到<code>WebsocketDataChangedListener</code>进行选择器数据变更处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"unchecked"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历数据变更监听器(一般使用一种数据同步的方式就好了)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataChangedListener</span><span class="token plain"> listener </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> listeners</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 哪种数据发生变更</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 省略了其他逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// WebsocketDataChangedListener进行选择器数据变更处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-websocket数据变更监听器">2.4 Websocket数据变更监听器<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#24-websocket%E6%95%B0%E6%8D%AE%E5%8F%98%E6%9B%B4%E7%9B%91%E5%90%AC%E5%99%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">
<p>WebsocketDataChangedListener.onSelectorChanged()</p>
<p>在<code>onSelectorChanged()</code>方法中，将数据进行了封装，转成<code>WebsocketData</code>，然后通过<code>WebsocketCollector.send()</code>发送数据。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器数据有更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorDataList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构造 WebsocketData 数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">WebsocketData</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> websocketData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">WebsocketData</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 通过websocket发送数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">WebsocketCollector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">send</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">websocketData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-websocket发送数据">2.5 Websocket发送数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#25-websocket%E5%8F%91%E9%80%81%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">WebsocketCollector.send()</li>
</ul>
<p>在<code>send()</code>方法中，判断了一下同步的类型，根据不同的类型，进行处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Slf4j</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ServerEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/websocket"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> configurator </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">WebsocketConfigurator</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">WebsocketCollector</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Send.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param message the message</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param type    the type</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">send</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> message</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 如果是MYSELF（第一次的全量同步）</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">MYSELF</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 从threadlocal中获取session</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Session</span><span class="token plain"> session </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Session</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token class-name">ThreadLocalUtil</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">SESSION_KEY</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">session </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 向该session发送全量数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token function" style="color:#d73a49">sendMessageBySession</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">session</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 后续的增量同步</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 向所有的session中同步变更数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token constant" style="color:#36acaa">SESSION_SET</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">session </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sendMessageBySession</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">session</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sendMessageBySession</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Session</span><span class="token plain"> session</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> message</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 通过websocket的session把消息发送出去</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            session</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBasicRemote</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sendText</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">IOException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"websocket send result is exception: "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>我们给的案例是一个新增操作 ，是一个增量同步，所以会走</p>
<p><code>SESSION_SET.forEach(session -&gt; sendMessageBySession(session, message));</code></p>
<p>这个逻辑。</p>
<p>再通过</p>
<p><code>session.getBasicRemote().sendText(message);</code></p>
<p>将数据发送了出去。</p>
<p>至此，当<code>admin</code>端发生数据变更时，就将变更的数据以增量形式通过<code>WebSocket</code>发给了网关。</p>
<p>分析到这里，不知道大家有没有疑问呢？比如<code>session</code>是怎么来的？网关如何和<code>admin</code>建立连接的？</p>
<p>不要着急，我们接下来就进行网关端的同步分析。</p>
<p>不过，在继续源码分析前，我们用一张图将上面的分析过程串联起来。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/websocket-data-sync-admin-56f75ad149ca3cd1ec07fd24c6194c5b.png" width="2361" height="747" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-网关数据同步">3. 网关数据同步<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#3-%E7%BD%91%E5%85%B3%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>假设<code>ShenYu</code>网关已经在正常运行了，使用的数据同步方式也是<code>websocket</code>。那么当在<code>admin</code>端新增一条选择器数据后，并且通过<code>WebSocket</code>发送到网关，那网关是如何接收并处理数据的呢？接下来我们就继续进行源码分析，一探究竟。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="31-websocketclient接收数据">3.1 WebsocketClient接收数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#31-websocketclient%E6%8E%A5%E6%94%B6%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">ShenyuWebsocketClient.onMessage()</li>
</ul>
<p>在网关端有一个<code>ShenyuWebsocketClient</code>类，它继承了<code>WebSocketClient</code>，可以和<code>WebSocket</code>建立连接并通信。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuWebsocketClient</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">WebSocketClient</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>当在<code>admin</code>端通过<code>websocket</code>发送数据后，<code>ShenyuWebsocketClient</code>就可以通过<code>onMessage()</code>接收到数据，然后就可以自己进行处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuWebsocketClient</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">WebSocketClient</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">// 接受到消息后执行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 处理接收到的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">handleResult</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleResult</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 数据反序列化</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">WebsocketData</span><span class="token plain"> websocketData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">WebsocketData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 哪种数据类型，插件、选择器、规则...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ConfigGroupEnum</span><span class="token plain"> groupEnum </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">acquireByName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">websocketData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 哪种操作类型，更新、删除...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> eventType </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> websocketData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> json </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">websocketData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 处理数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        websocketDataHandler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">executor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">groupEnum</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>接收到数据后，首先进行了反序列化操作，读取数据类型和操作类型，紧接着，就交给<code>websocketDataHandler.executor()</code>进行处理。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="32-执行websocket事件处理器">3.2 执行Websocket事件处理器<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#32-%E6%89%A7%E8%A1%8Cwebsocket%E4%BA%8B%E4%BB%B6%E5%A4%84%E7%90%86%E5%99%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">WebsocketDataHandler.executor()</li>
</ul>
<p>通过工厂模式创建了<code>Websocket</code>数据处理器，每种数据类型，都提供了一个处理器：</p>
<blockquote>
<p>插件 --&gt; 插件数据处理器;</p>
<p>选择器 --&gt; 选择器数据处理器；</p>
<p>规则 --&gt; 规则数据处理器；</p>
<p>认证信息 --&gt; 认证数据处理器；</p>
<p>元数据 --&gt; 元数据处理器。</p>
</blockquote>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 通过工厂模式创建 Websocket数据处理器</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type Websocket cache handler.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">WebsocketDataHandler</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">EnumMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConfigGroupEnum</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">DataHandler</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">ENUM_MAP</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">EnumMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Instantiates a new Websocket data handler.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 每种数据类型，提供一个处理器</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param pluginDataSubscriber the plugin data subscriber</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param metaDataSubscribers  the meta data subscribers</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param authDataSubscribers  the auth data subscribers</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">WebsocketDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginDataSubscriber</span><span class="token plain"> pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AuthDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> authDataSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 插件 --&gt; 插件数据处理器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">ENUM_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">PluginDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器 --&gt; 选择器数据处理器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">ENUM_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">SelectorDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 规则 --&gt; 规则数据处理器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">ENUM_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RULE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">RuleDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 认证信息 --&gt; 认证数据处理器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">ENUM_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APP_AUTH</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">AuthDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authDataSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据 --&gt; 元数据处理器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">ENUM_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">MetaDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Executor.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param type      the type</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param json      the json</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param eventType the event type</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">executor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConfigGroupEnum</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 根据数据类型，找到对应的数据处理器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">ENUM_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">type</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">json</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>不同的数据类型，有不同的数据处理方式，所以有不同的实现类。但是它们之间也有相同的处理逻辑，所以可以通过模板方法设计模式来实现。相同的逻辑放在抽象类中的<code>handle()</code>方法中，不同逻辑就交给各自的实现类。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/data-handler-313ae788eadfdabf405cdc55c74dbb21.png" width="1947" height="449" class="img_ev3q"></p>
<p>我们的案例是新增了一条选择器数据，所以会交给<code>SelectorDataHandler</code>（ 选择器 --&gt; 选择器数据处理器）进行数据处理。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="33-判断事件类型">3.3 判断事件类型<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#33-%E5%88%A4%E6%96%AD%E4%BA%8B%E4%BB%B6%E7%B1%BB%E5%9E%8B" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">AbstractDataHandler.handle()</li>
</ul>
<p>实现数据变更的通用逻辑处理：根据不同的操作类型调用不同方法。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractDataHandler</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">DataHandler</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Convert list.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 不同的逻辑由各自实现类去实现</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param json the json</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the list</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">convert</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Do refresh.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 不同的逻辑由各自实现类去实现</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param dataList the data list</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doRefresh</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> dataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Do update.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 不同的逻辑由各自实现类去实现</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param dataList the data list</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> dataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Do delete.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 不同的逻辑由各自实现类去实现</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param dataList the data list</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doDelete</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> dataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 通用逻辑，抽象类实现</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> dataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">convert</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventTypeEnum </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">acquireByName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">eventTypeEnum</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">REFRESH</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">MYSELF</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token function" style="color:#d73a49">doRefresh</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">//刷新数据，全量同步</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">CREATE</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token function" style="color:#d73a49">doUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新或创建数据，增量同步</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token function" style="color:#d73a49">doDelete</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 删除数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">default</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>新增一条选择器数据，是新增操作，通过<code>switch-case</code>进入到<code>doUpdate()</code>方法中。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="34-进入具体的数据处理器">3.4 进入具体的数据处理器<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#34-%E8%BF%9B%E5%85%A5%E5%85%B7%E4%BD%93%E7%9A%84%E6%95%B0%E6%8D%AE%E5%A4%84%E7%90%86%E5%99%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">SelectorDataHandler.doUpdate()</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 选择器数据处理器</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type Selector data handler.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequiredArgsConstructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SelectorDataHandler</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractDataHandler</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginDataSubscriber</span><span class="token plain"> pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> dataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        dataList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataSubscriber</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">onSelectorSubscribe</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>遍历数据，进入<code>onSelectorSubscribe()</code>方法。</p>
<ul>
<li class="">PluginDataSubscriber.onSelectorSubscribe()</li>
</ul>
<p>它没有其他逻辑，直接调用<code>subscribeDataHandler()</code>方法。在方法中，更具数据类型（插件、选择器或规则），操作类型（更新或删除），去执行不同逻辑。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 通用插件数据订阅者，负责处理所有插件、选择器和规则信息</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type Common plugin data subscriber.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">CommonPluginDataSubscriber</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">PluginDataSubscriber</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">// 处理选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onSelectorSubscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">subscribeDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅数据处理器，处理数据的更新或删除</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">subscribeDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token plain"> classData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> dataType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">classData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">PluginData</span><span class="token plain"> pluginData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cachePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handlerPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 从网关内存移除数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removePlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cacheSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理 </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handlerSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 从网关内存移除数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">RuleData</span><span class="token plain"> ruleData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RuleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cacheRuleData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handlerRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 从网关内存移除数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeRuleData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>那么新增一条选择器数据，会进入下面的逻辑：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cacheSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理                  </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handlerSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>一是将数据保存到网关的内存中。<code>BaseDataCache</code>是最终缓存数据的类，通过单例模式实现。选择器数据就存到了<code>SELECTOR_MAP</code>这个<code>Map</code>中。在后续使用的时候，也是从这里拿数据。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 私有变量</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  	</span><span class="token comment" style="color:#999988;font-style:italic">// 私有构造器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Gets instance.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *  公开方法</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the instance</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">    *  缓存选择器数据的Map</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * pluginName -&gt; SelectorData.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConcurrentMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Maps</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newConcurrentMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">cacheSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">selectorAccept</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * cache selector data.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 缓存选择器数据</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param data the selector data</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">selectorAccept</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">containsKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作，先删除再插入</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> existList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> resultList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> existList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">r </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">r</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            resultList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> collect </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> resultList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sorted</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Comparator</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comparing</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorData</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">getSort</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> collect</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 新增操作，直接放到Map中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Lists</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newArrayList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>二是如果每个插件还有自己的处理逻辑，那么就去处理。  通过<code>idea</code>编辑器可以看到，当新增一条选择器后，有如下的插件还有处理。这里我们就不再展开了。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/handler-selector-bf05b8fdf80a428aa53606178a42bae6.png" width="2456" height="617" class="img_ev3q"></p>
<p>经过以上的源码追踪，并通过一个实际的案例，在<code>admin</code>端新增一条选择器数据，就将<code>websocket</code>数据同步的流程分析清楚了。</p>
<p>我们还是用下面的一张图将网关端的数据同步流程串联一下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/websocket-data-sync-gateway-181e89c69dc9b9d2569e858eb82431bf.png" width="2348" height="798" class="img_ev3q"></p>
<p>数据同步的流程已经分析完了，但是还有一些问题没有分析到，就是网关是如何跟<code>admin</code>建立连接的？</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-网关和admin建立websocket连接">4. 网关和admin建立websocket连接<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#4-%E7%BD%91%E5%85%B3%E5%92%8Cadmin%E5%BB%BA%E7%AB%8Bwebsocket%E8%BF%9E%E6%8E%A5" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<ul>
<li class="">websocket配置</li>
</ul>
<p>在网关的配置文件中有如下配置，并且引入了相关依赖，就会启动<code>websocket</code>相关服务。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">file</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">cross</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">dubbo</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">parameter</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> multi</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">sync</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">websocket</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># 使用websocket进行数据同步</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">urls</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ws</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//localhost</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">9095/websocket   </span><span class="token comment" style="color:#999988;font-style:italic"># admin端的websocket地址</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">allowOrigin</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ws</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//localhost</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">9195</span><br></span></code></pre></div></div>
<p>在网关中引入<code>websocket</code>的依赖。</p>
<div class="language-xml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-xml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">&lt;!--shenyu data sync start use websocket--&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">dependency</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">groupId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">org.apache.shenyu</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">groupId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">artifactId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">shenyu-spring-boot-starter-sync-data-websocket</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">artifactId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">version</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">${project.version}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">version</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">dependency</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<ul>
<li class="">Websocket数据同步配置</li>
</ul>
<p>通过<code>springboot</code>的条件装配，创建相关的<code>bean</code>。在网关启动的时候，如果我们配置了<code>shenyu.sync.websocket.urls</code>，那么<code>Websocket</code>数据同步配置就会被加载。这里通过<code>spring boot starter</code>完成依赖的加载。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Websocket数据同步配置</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 通过springboot实现条件注入</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Websocket sync data configuration for spring boot.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnClass</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">WebsocketSyncDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.sync.websocket"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"urls"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Slf4j</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">WebsocketSyncDataConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Websocket sync data service.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Websocket数据同步服务</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param websocketConfig   the websocket config</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param pluginSubscriber the plugin subscriber</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param metaSubscribers   the meta subscribers</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param authSubscribers   the auth subscribers</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the sync data service</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 创建websocketSyncDataService</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">websocketSyncDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">WebsocketConfig</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> websocketConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> pluginSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                           </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ObjectProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AuthDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> authSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"you use websocket sync shenyu data......."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">WebsocketSyncDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">websocketConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">WebsocketConfig</span><span class="token operator" style="color:#393A34">::</span><span class="token keyword" style="color:#00009f">new</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginSubscriber</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                metaSubscribers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collections</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">emptyList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> authSubscribers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getIfAvailable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collections</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">emptyList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Config websocket config.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the websocket config</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.sync.websocket"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">WebsocketConfig</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">websocketConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">WebsocketConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 创建WebsocketConfig</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>在项目的<code>resources/META-INF</code>目录先新建<code>spring.factories</code>文件，在文件中指明配置类。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/websocket-springboot-starter-2cfd149ba2fb69ab514241e061fc22c9.png" width="2275" height="434" class="img_ev3q"></p>
<ul>
<li class="">Websocket数据同步服务</li>
</ul>
<p>在<code>WebsocketSyncDataService</code>中做了如下几件事情：</p>
<ul>
<li class="">读取配置中的<code>urls</code>，这个表示<code>admin</code>端的同步地址，有多个的话，使用","分割；</li>
<li class="">创建调度线程池，一个<code>admin</code>分配一个，用于执行定时任务；</li>
<li class="">创建<code>ShenyuWebsocketClient</code>，一个<code>admin</code>分配一个，用于和<code>admin</code>建立<code>websocket</code>通信；</li>
<li class="">开始和<code>admin</code>端的<code>websocket</code> 建立连接；</li>
<li class="">执行定时任务，每隔10秒执行一次。主要作用是判断<code>websocket</code>连接是否已经断开，如果已经断开，则尝试重连。如果没有断开，就进行 <code>ping-pong</code> 检测。</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Websocket数据同步服务</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Websocket sync data service.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Slf4j</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">WebsocketSyncDataService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">AutoCloseable</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">WebSocketClient</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> clients </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ArrayList</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ScheduledThreadPoolExecutor</span><span class="token plain"> executor</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Instantiates a new Websocket sync cache.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 创建Websocket数据同步服务</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param websocketConfig      the websocket config</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param pluginDataSubscriber the plugin data subscriber</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param metaDataSubscribers  the meta data subscribers</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param authDataSubscribers  the auth data subscribers</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">WebsocketSyncDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">WebsocketConfig</span><span class="token plain"> websocketConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginDataSubscriber</span><span class="token plain"> pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                    </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AuthDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> authDataSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// admin端的同步地址，有多个的话，使用","分割</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> urls </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">split</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">websocketConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUrls</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">","</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 创建调度线程池，一个admin分配一个</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        executor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ScheduledThreadPoolExecutor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">urls</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">length</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuThreadFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"websocket-connect"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> url </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> urls</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">//创建WebsocketClient，一个admin分配一个</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                clients</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuWebsocketClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">URI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">url</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">requireNonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> authDataSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">URISyntaxException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"websocket url({}) is error"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">WebSocketClient</span><span class="token plain"> client </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> clients</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 和websocket server建立连接</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> success </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">connectBlocking</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">3000</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">MILLISECONDS</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">success</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"websocket connection is successful....."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"websocket connection is error....."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 执行定时任务，每隔10秒执行一次</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 主要作用是判断websocket连接是否已经断开，如果已经断开，则尝试重连。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 如果没有断开，就进行 ping-pong 检测</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                executor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">scheduleAtFixedRate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isClosed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> reconnectSuccess </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">reconnectBlocking</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">reconnectSuccess</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"websocket reconnect server[{}] is successful....."</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"websocket reconnection server[{}] is error....."</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sendPing</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">debug</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"websocket send to [{}] ping message successful"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">InterruptedException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"websocket connect is error :{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SECONDS</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">/* client.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxyaddress", 80)));*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">InterruptedException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"websocket connection...exception...."</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">close</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 关闭 websocket client</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">WebSocketClient</span><span class="token plain"> client </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> clients</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isClosed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">close</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 关闭线程池</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">executor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            executor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">shutdown</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">ShenyuWebsocketClient</li>
</ul>
<p>在<code>ShenYu</code>中创建的<code>WebSocket</code>客户端，用于和<code>admin</code>端通信。第一次成功建立连接后，同步全量数据，后续进行增量同步。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 在ShenYu中自定义的WebSocket客户端</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type shenyu websocket client.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Slf4j</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuWebsocketClient</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">WebSocketClient</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">volatile</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> alreadySync </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">FALSE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">WebsocketDataHandler</span><span class="token plain"> websocketDataHandler</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Instantiates a new shenyu websocket client.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 创建ShenyuWebsocketClient</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param serverUri             the server uri  服务端uri</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param pluginDataSubscriber the plugin data subscriber 插件数据订阅器</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param metaDataSubscribers   the meta data subscribers 元数据订阅器</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param authDataSubscribers   the auth data subscribers 认证数据订阅器</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuWebsocketClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">URI</span><span class="token plain"> serverUri</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginDataSubscriber</span><span class="token plain"> pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AuthDataSubscriber</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> authDataSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">super</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serverUri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">websocketDataHandler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">WebsocketDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> authDataSubscribers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 成功建立连接后执行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onOpen</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerHandshake</span><span class="token plain"> serverHandshake</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 防止重新建立连接时，再次执行，所以用alreadySync进行判断</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">alreadySync</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 同步所有数据，MYSELF 类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">send</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">MYSELF</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            alreadySync </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 接收到消息后执行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 处理接收到的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">handleResult</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 关闭后执行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onClose</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> s</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">close</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 失败后执行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">close</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"ALL"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleResult</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 数据反序列化</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">WebsocketData</span><span class="token plain"> websocketData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">WebsocketData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 哪种数据类型，插件、选择器、规则...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ConfigGroupEnum</span><span class="token plain"> groupEnum </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">acquireByName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">websocketData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 哪种操作类型，更新、删除...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> eventType </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> websocketData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> json </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">websocketData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 处理数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        websocketDataHandler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">executor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">groupEnum</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-总结">5. 总结<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync#5-%E6%80%BB%E7%BB%93" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>本文通过一个实际案例，对<code>websocket</code>的数据同步原理进行了源码分析。涉及到的主要知识点如下：</p>
<ul>
<li class=""><code>websocket</code>支持双向通信，性能好，推荐使用；</li>
<li class="">通过<code>Spring</code>完成事件发布和监听；</li>
<li class="">通过抽象<code>DataChangedListener</code>接口，支持多种同步策略，面向接口编程；</li>
<li class="">使用工厂模式创建 <code>WebsocketDataHandler</code>，实现不同数据类型的处理；</li>
<li class="">使用模板方法设计模式实现<code>AbstractDataHandler</code>，处理通用的操作类型；</li>
<li class="">使用单例设计模式实现缓存数据类<code>BaseDataCache</code>；</li>
<li class="">通过<code>SpringBoot</code>的条件装配和<code>starter</code>加载机制实现配置类的加载。</li>
</ul>]]></content>
        <author>
            <name>midnight2104</name>
            <uri>https://github.com/midnight2104</uri>
        </author>
        <category label="websocket" term="websocket"/>
        <category label="data sync" term="data sync"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[ZooKeeper数据同步源码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync</id>
        <link href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[Apache ShenYu 是一个异步的，高性能的，跨语言的，响应式的 API 网关。]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p><a href="https://shenyu.apache.org/zh/docs/index" target="_blank" rel="noopener noreferrer" class="">Apache ShenYu</a> 是一个异步的，高性能的，跨语言的，响应式的 <code>API</code> 网关。</p>
</blockquote>
<p>在<code>ShenYu</code>网关中，数据同步是指，当在后台管理系统中，数据发送了更新后，如何将更新的数据同步到网关中。<code>Apache ShenYu</code> 网关当前支持<code>ZooKeeper</code>、<code>WebSocket</code>、<code>Http长轮询</code>、<code>Nacos</code> 、<code>Etcd</code> 和 <code>Consul</code> 进行数据同步。本文的主要内容是基于<code>ZooKeeper</code>的数据同步源码分析。</p>
<blockquote>
<p>本文基于<code>shenyu-2.4.0</code>版本进行源码分析，官网的介绍请参考 <a href="https://shenyu.apache.org/zh/docs/design/data-sync" target="_blank" rel="noopener noreferrer" class="">数据同步原理</a> 。</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-关于zookeeper">1. 关于ZooKeeper<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#1-%E5%85%B3%E4%BA%8Ezookeeper" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p><a href="https://zh.wikipedia.org/wiki/Apache_ZooKeeper" target="_blank" rel="noopener noreferrer" class=""><code>Apache ZooKeeper</code></a>是<code>Apache</code>软件基金会的一个软件项目，它为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册。<code>ZooKeeper</code>节点将它们的数据存储于一个分层的名字空间，非常类似于一个文件系统或一个前缀树结构。客户端可以在节点读写，从而以这种方式拥有一个共享的配置服务。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-admin数据同步">2. Admin数据同步<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#2-admin%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>我们从一个实际案例进行源码追踪，比如在后台管理系统中，对<code>Divide</code>插件中的一条选择器数据进行更新，将权重更新为90：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/update-selector-zh-1f49b39fb8e5ce2c26a80018669619ea.png" width="2385" height="1185" class="img_ev3q"></p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="21-接收数据">2.1 接收数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#21-%E6%8E%A5%E6%94%B6%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">SelectorController.createSelector()</li>
</ul>
<p>进入<code>SelectorController</code>类中的<code>updateSelector()</code>方法，它负责数据的校验，添加或更新数据，返回结果信息。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Validated</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequiredArgsConstructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RestController</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequestMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/selector"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SelectorController</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@PutMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/{id}"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuAdminResult</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">updateSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@PathVariable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"id"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@Valid</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@RequestBody</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 设置当前选择器数据id</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 创建或更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Integer</span><span class="token plain"> updateCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createOrUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 返回结果信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuAdminResult</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">success</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE_SUCCESS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> updateCount</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="22-处理数据">2.2 处理数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#22-%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">SelectorServiceImpl.createOrUpdate()</li>
</ul>
<p>在<code>SelectorServiceImpl</code>类中通过<code>createOrUpdate()</code>方法完成数据的转换，保存到数据库，发布事件，更新<code>upstream</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@RequiredArgsConstructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SelectorServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SelectorService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 负责事件发布的eventPublisher</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApplicationEventPublisher</span><span class="token plain"> eventPublisher</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Transactional</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rollbackFor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createOrUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> selectorCount</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建数据 DTO --&gt; DO</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SelectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorConditionDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorConditionDTOs </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSelectorConditions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 判断是添加还是更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插入选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插入选择器中的条件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setSelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorConditionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorConditionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// check selector add</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 权限检查</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataPermissionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listByUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">JwtUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserInfo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">DataPermissionDTO</span><span class="token plain"> dataPermissionDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataPermissionDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">JwtUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserInfo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUserId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setDataId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setDataType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">AdminConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR_DATA_TYPE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                dataPermissionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataPermissionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildPermissionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataPermissionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 更新数据，先删除再新增</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//delete rule condition then add</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">deleteByQuery</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">SelectorConditionQuery</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setSelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">SelectorConditionDO</span><span class="token plain"> selectorConditionDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SelectorConditionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorConditionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发布事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 更新upstream</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">updateDivideUpstream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> selectorCount</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>在<code>Serrvice</code>类完成数据的持久化操作，即保存数据到数据库，这个比较简单，就不深入追踪了。关于更新<code>upstream</code>操作，放到后面对应的章节中进行分析，重点关注发布事件的操作，它会执行数据同步。</p>
<p><code>publishEvent()</code>方法的逻辑是：找到选择器对应的插件，构建条件数据，发布变更数据。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">       </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorConditionDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 找到选择器对应的插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PluginDO</span><span class="token plain"> pluginDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pluginMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selectById</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建条件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConditionData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> conditionDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain">                selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConditionTransfer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">mapToSelectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发布变更数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">transFrom</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> conditionDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>发布变更数据通过<code>eventPublisher.publishEvent()</code>完成，这个<code>eventPublisher</code>对象是一个<code>ApplicationEventPublisher</code>类，这个类的全限定名是<code>org.springframework.context.ApplicationEventPublisher</code>。看到这儿，我们知道了发布数据是通过<code>Spring</code>相关的功能来完成的。</p>
<blockquote>
<p>关于<code>ApplicationEventPublisher</code>：</p>
<p>当有状态发生变化时，发布者调用 <code>ApplicationEventPublisher</code> 的 <code>publishEvent</code> 方法发布一个事件，<code>Spring</code>容器广播事件给所有观察者，调用观察者的 <code>onApplicationEvent</code> 方法把事件对象传递给观察者。调用 <code>publishEvent</code>方法有两种途径，一种是实现接口由容器注入 <code>ApplicationEventPublisher</code> 对象然后调用其方法，另一种是直接调用容器的方法，两种方法发布事件没有太大区别。</p>
<ul>
<li class=""><code>ApplicationEventPublisher</code>：发布事件；</li>
<li class=""><code>ApplicationEvent</code>：<code>Spring</code> 事件，记录事件源、时间和数据；</li>
<li class=""><code>ApplicationListener</code>：事件监听者，观察者；</li>
</ul>
</blockquote>
<p>在<code>Spring</code>的事件发布机制中，有三个对象，</p>
<p>一个是发布事件的<code>ApplicationEventPublisher</code>，在<code>ShenYu</code>中通过构造器注入了一个<code>eventPublisher</code>。</p>
<p>另一个对象是<code>ApplicationEvent</code>，在<code>ShenYu</code>中通过<code>DataChangedEvent</code>继承了它，表示事件对象。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">ApplicationEvent</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>最后一个是 <code>ApplicationListener</code>，在<code>ShenYu</code>中通过<code>DataChangedEventDispatcher</code>类实现了该接口，作为事件的监听者，负责处理事件对象。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEventDispatcher</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataChangedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="23-分发数据">2.3 分发数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#23-%E5%88%86%E5%8F%91%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">DataChangedEventDispatcher.onApplicationEvent()</li>
</ul>
<p>当事件发布完成后，会自动进入到<code>DataChangedEventDispatcher</code>类中的<code>onApplicationEvent()</code>方法，进行事件处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataChangedEventDispatcher</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataChangedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InitializingBean</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 有数据变更时，调用此方法</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param event</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"unchecked"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历数据变更监听器(一般使用一种数据同步的方式就好了)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataChangedListener</span><span class="token plain"> listener </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> listeners</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 哪种数据发生变更</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">APP_AUTH</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 认证信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onAppAuthChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">AppAuthData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 插件信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onPluginChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">RULE</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onRuleChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onMetaDataChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">default</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 其他类型，抛出异常</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">IllegalStateException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Unexpected value: "</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>当有数据变更时，调用<code>onApplicationEvent</code>方法，然后遍历所有数据变更监听器，判断是哪种数据类型，交给相应的数据监听器进行处理。</p>
<p><code>ShenYu</code>将所有数据进行了分组，一共是五种：认证信息、插件信息、规则信息、选择器信息和元数据。</p>
<p>这里的数据变更监听器（<code>DataChangedListener</code>），就是数据同步策略的抽象，它的具体实现有：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/data-changed-listener-b01d7410746ca4afd526d8c9df865e9b.png" width="1966" height="482" class="img_ev3q"></p>
<p>这几个实现类就是当前<code>ShenYu</code>支持的同步策略：</p>
<ul>
<li class=""><code>WebsocketDataChangedListener</code>：基于<code>websocket</code>的数据同步；</li>
<li class=""><code>ZookeeperDataChangedListener</code>：基于<code>zookeeper</code>的数据同步；</li>
<li class=""><code>ConsulDataChangedListener</code>：基于<code>consul</code>的数据同步；</li>
<li class=""><code>EtcdDataDataChangedListener</code>：基于<code>etcd</code>的数据同步；</li>
<li class=""><code>HttpLongPollingDataChangedListener</code>：基于<code>http长轮询</code>的数据同步；</li>
<li class=""><code>NacosDataChangedListener</code>：基于<code>nacos</code>的数据同步；</li>
</ul>
<p>既然有这么多种实现策略，那么如何确定使用哪一种呢？</p>
<p>因为本文是基于<code>Zookeeper</code>的数据同步源码分析，所以这里以<code>ZookeeperDataChangedListener</code>为例，分析它是如何被加载并实现的。</p>
<p>通过在源码工程中进行全局搜索，可以看到，它的实现是在<code>DataSyncConfiguration</code>类完成的。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 数据同步配置类</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 通过springboot条件装配实现</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type Data sync configuration.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DataSyncConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * zookeeper数据同步</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The type Zookeeper listener.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.sync.zookeeper"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"url"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 条件属性，满足才会被加载</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Import</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ZookeeperConfiguration</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ZookeeperListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Config event listener data changed listener.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * 创建Zookeeper数据变更监听器</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param zkClient the zk client</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the data changed listener</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnMissingBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ZookeeperDataChangedListener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">DataChangedListener</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">zookeeperDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ZkClient</span><span class="token plain"> zkClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ZookeeperDataChangedListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">zkClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Zookeeper data init zookeeper data init.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *  创建 Zookeeper 数据初始化类</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param zkClient        the zk client</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param syncDataService the sync data service</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return the zookeeper data init</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnMissingBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ZookeeperDataInit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ZookeeperDataInit</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">zookeeperDataInit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ZkClient</span><span class="token plain"> zkClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ZookeeperDataInit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">zkClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//省略了其他代码......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>这个配置类是通过<code>SpringBoot</code>条件装配类实现的。在<code>ZookeeperListener</code>类上面有几个注解：</p>
<ul>
<li class="">
<p><code>@Configuration</code>：配置文件，应用上下文；</p>
</li>
<li class="">
<p><code>@ConditionalOnProperty(prefix = "shenyu.sync.zookeeper", name = "url")</code>：属性条件判断，满足条件，该配置类才会生效。也就是说，当我们有如下配置时，就会采用<code>zookeeper</code>进行数据同步。</p>
<div class="language-properties codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-properties codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key attr-name" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">  sync</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">     zookeeper</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">          url</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token value attr-value" style="color:#e3116c">localhost:2181</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">          sessionTimeout</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token value attr-value" style="color:#e3116c">5000</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">          connectionTimeout</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token value attr-value" style="color:#e3116c">2000</span><br></span></code></pre></div></div>
</li>
<li class="">
<p><code>@Import(ZookeeperConfiguration.class)</code>：导入另一个类<code>ZookeeperConfiguration</code>；</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token annotation punctuation" style="color:#393A34">@EnableConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ZookeeperProperties</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 启用zk属性配置类</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ZookeeperConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * register zkClient in spring ioc.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 向 Spring IOC 容器注册 zkClient</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param zookeeperProp the zookeeper configuration</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return ZkClient {@linkplain ZkClient}</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">        */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnMissingBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ZkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ZkClient</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">zkClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ZookeeperProperties</span><span class="token plain"> zookeeperProp</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ZkClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">zookeeperProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> zookeeperProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSessionTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> zookeeperProp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getConnectionTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 读取zk配置信息，并创建zkClient</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Data</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.sync.zookeeper"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// zk属性配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ZookeeperProperties</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Integer</span><span class="token plain"> sessionTimeout</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Integer</span><span class="token plain"> connectionTimeout</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> serializer</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>当我们主动配置，采用<code>zookeeper</code>进行数据同步时，<code>zookeeperDataChangedListener</code>就会生成。所以在事件处理方法<code>onApplicationEvent()</code>中，就会到相应的<code>listener</code>中。在我们的案例中，是对一条选择器数据进行更新，数据同步采用的是<code>zookeeper</code>，所以，代码会进入到<code>ZookeeperDataChangedListener</code>进行选择器数据变更处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"unchecked"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历数据变更监听器(一般使用一种数据同步的方式就好了)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataChangedListener</span><span class="token plain"> listener </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> listeners</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 哪种数据发生变更</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroupKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 省略了其他逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token operator" style="color:#393A34">:</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    listener</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 在我们的案例中，会进入到ZookeeperDataChangedListener进行选择器数据变更处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-zookeeper数据变更监听器">2.4 Zookeeper数据变更监听器<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#24-zookeeper%E6%95%B0%E6%8D%AE%E5%8F%98%E6%9B%B4%E7%9B%91%E5%90%AC%E5%99%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">
<p>ZookeeperDataChangedListener.onSelectorChanged()</p>
<p>在<code>onSelectorChanged()</code>方法中，判断操作类型，是刷新同步还是更新或创建同步。根据当前选择器数据信息判断节点是否在<code>zk</code>中。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 使用 zookeeper 发布变更数据</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ZookeeperDataChangedListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">DataChangedListener</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息发生改变</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onSelectorChanged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 刷新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">eventType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">REFRESH</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">changed</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">String</span><span class="token plain"> selectorParentPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorParentPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">changed</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">deleteZkPathRecursive</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorParentPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发生变更的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorData</span><span class="token plain"> data </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> changed</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 构建选择器数据的真实路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">String</span><span class="token plain"> selectorRealPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorRealPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 如果是删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">eventType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 删除当前数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token function" style="color:#d73a49">deleteZkPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorRealPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">continue</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 父节点路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">String</span><span class="token plain"> selectorParentPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorParentPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 创建父节点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">createZkNode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorParentPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插入或更新数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">insertZkNode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorRealPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// 创建 zk 节点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createZkNode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 不存在才创建</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">zkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            zkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createPersistent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 插入zk节点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">insertZkNode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 创建节点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">createZkNode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 通过 zkClient 写入数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        zkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">writeData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> data </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>只要将变动的数据正确写入到<code>zk</code>的节点上，<code>admin</code>这边的操作就执行完成了。<code>ShenYu</code>在使用<code>zk</code>进行数据同步时，<code>zk</code>的节点是通过精心设计的。</p>
<p>在我们当前的案例中，对<code>Divide</code>插件中的一条选择器数据进行更新，将权重更新为90，就会对图中的特定节点更新。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/zookeeper-node-c7628b680a1f1afa0eada97b66fcd5b1.png" width="1704" height="1140" class="img_ev3q"></p>
<p>我们用时序图将上面的更新流程串联起来。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/zk-sync-sequence-admin-zh-afad1ef642b7130231c2ceacce236b34.png" width="2401" height="880" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-网关数据同步">3. 网关数据同步<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#3-%E7%BD%91%E5%85%B3%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>假设<code>ShenYu</code>网关已经在正常运行，使用的数据同步方式也是<code>zookeeper</code>。那么当在<code>admin</code>端更新选择器数据后，并且向<code>zk</code>发送了变更的数据，那网关是如何接收并处理数据的呢？接下来我们就继续进行源码分析，一探究竟。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="31-zkclient接收数据">3.1 ZkClient接收数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#31-zkclient%E6%8E%A5%E6%94%B6%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">ZkClient.subscribeDataChanges()</li>
</ul>
<p>在网关端有一个<code>ZookeeperSyncDataService</code>类，它通过<code>ZkClient</code>订阅了数据节点，当数据发生变更时，可以感知到。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 使用 zookeeper 缓存数据</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ZookeeperSyncDataService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">AutoCloseable</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">subscribeSelectorDataChanges</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       </span><span class="token comment" style="color:#999988;font-style:italic">// zkClient订阅数据节点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        zkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">subscribeDataChanges</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">IZkDataListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleDataChange</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> dataPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token function" style="color:#d73a49">cacheSelectorData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 节点数据被更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleDataDeleted</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> dataPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token function" style="color:#d73a49">unCacheSelectorData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 节点数据被删除</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 省略了其他逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>ZooKeeper</code>的<code>Watch</code>机制，会给订阅的客户端发送节点变更通知。在我们的案例中，更新选择器信息，就会进入到<code>handleDataChange()</code>方法。通过<code>cacheSelectorData()</code>去处理数据。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="32-处理数据">3.2 处理数据<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#32-%E5%A4%84%E7%90%86%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">ZookeeperSyncDataService.cacheSelectorData()</li>
</ul>
<p>经过判空逻辑之后，缓存选择器数据的操作又交给了<code>PluginDataSubscriber</code>处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">cacheSelectorData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSelectorSubscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>PluginDataSubscriber</code>是一个接口，它只有一个<code>CommonPluginDataSubscriber</code>实现类，负责处理插件、选择器和规则数据。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="33-通用插件数据订阅者">3.3 通用插件数据订阅者<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#33-%E9%80%9A%E7%94%A8%E6%8F%92%E4%BB%B6%E6%95%B0%E6%8D%AE%E8%AE%A2%E9%98%85%E8%80%85" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">PluginDataSubscriber.onSelectorSubscribe()</li>
</ul>
<p>它没有其他逻辑，直接调用<code>subscribeDataHandler()</code>方法。在方法中，更具数据类型（插件、选择器或规则），操作类型（更新或删除），去执行不同逻辑。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 通用插件数据订阅者，负责处理所有插件、选择器和规则信息</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The type Common plugin data subscriber.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">CommonPluginDataSubscriber</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">PluginDataSubscriber</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">// 处理选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onSelectorSubscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">subscribeDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅数据处理器，处理数据的更新或删除</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">subscribeDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token plain"> classData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> dataType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">classData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">PluginData</span><span class="token plain"> pluginData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cachePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handlerPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 从网关内存移除数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removePlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cacheSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理                    Optional.ofNullable(handlerMap.get(selectorData.getPluginName())).ifPresent(handler -&gt; handler.handlerSelector(selectorData));</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 从网关内存移除数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">RuleData</span><span class="token plain"> ruleData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RuleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cacheRuleData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handlerRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataType </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 从网关内存移除数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeRuleData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="34-数据缓存到内存">3.4 数据缓存到内存<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#34-%E6%95%B0%E6%8D%AE%E7%BC%93%E5%AD%98%E5%88%B0%E5%86%85%E5%AD%98" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>那么更新一条选择器数据，会进入下面的逻辑：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 将数据保存到网关内存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cacheSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 如果每个插件还有自己的处理逻辑，那么就去处理                    </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handlerSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>一是将数据保存到网关的内存中。<code>BaseDataCache</code>是最终缓存数据的类，通过单例模式实现。选择器数据就存到了<code>SELECTOR_MAP</code>这个<code>Map</code>中。在后续使用的时候，也是从这里拿数据。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 私有变量</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  	</span><span class="token comment" style="color:#999988;font-style:italic">// 私有构造器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Gets instance.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *  公开方法</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the instance</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">    *  缓存选择器数据的Map</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * pluginName -&gt; SelectorData.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConcurrentMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Maps</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newConcurrentMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">cacheSelectData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">selectorAccept</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * cache selector data.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 缓存选择器数据</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param data the selector data</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">selectorAccept</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">containsKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作，先删除再插入</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> existList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> resultList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> existList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">r </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">r</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            resultList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> collect </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> resultList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sorted</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Comparator</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">comparing</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorData</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">getSort</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> collect</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 新增操作，直接放到Map中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">SELECTOR_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Lists</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newArrayList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>二是如果每个插件还有自己的处理逻辑，那么就去处理。  通过<code>idea</code>编辑器可以看到，当新增一条选择器后，有如下的插件还有处理。这里我们就不再展开了。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/handler-selector-bf05b8fdf80a428aa53606178a42bae6.png" width="2456" height="617" class="img_ev3q"></p>
<p>经过以上的源码追踪，并通过一个实际的案例，在<code>admin</code>端新增更新一条选择器数据，就将<code>zookeeper</code>数据同步的流程分析清楚了。</p>
<p>我们还是通过时序图将网关端的数据同步流程串联一下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/zk-sync-sequence-gateway-zh-0494aedc4de3f64c781fe8bb6c4b69bc.png" width="1620" height="807" class="img_ev3q"></p>
<p>数据同步的流程已经分析完了，为了不让同步流程被打断，在分析过程中就忽略了其他逻辑。我们还需要分析<code>Admin</code>同步数据初始化和网关同步操作初始化的流程。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-admin同步数据初始化">4. Admin同步数据初始化<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#4-admin%E5%90%8C%E6%AD%A5%E6%95%B0%E6%8D%AE%E5%88%9D%E5%A7%8B%E5%8C%96" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>当<code>admin</code>启动后，会将当前的数据信息全量同步到<code>zk</code>中，实现逻辑如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Zookeeper 数据初始化</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ZookeeperDataInit</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">CommandLineRunner</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ZkClient</span><span class="token plain"> zkClient</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Instantiates a new Zookeeper data init.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param zkClient        the zk client</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param syncDataService the sync data service</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ZookeeperDataInit</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ZkClient</span><span class="token plain"> zkClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">zkClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> zkClient</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">syncDataService </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> syncDataService</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> args</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> pluginPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN_PARENT</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> authPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APP_AUTH_PARENT</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> metaDataPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 判断zk中是否存在数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">zkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">zkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">zkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            syncDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">syncAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">REFRESH</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>判断<code>zk</code>中是否存在数据，如果不存在，则进行同步。</p>
<p><code>ZookeeperDataInit</code>实现了<code>CommandLineRunner</code>接口。它是<code>springboot</code>提供的接口，会在所有 <code>Spring Beans</code>初始化之后执行<code>run()</code>方法，常用于项目中初始化的操作。</p>
<ul>
<li class="">SyncDataService.syncAll()</li>
</ul>
<p>从数据库查询数据，然后进行全量数据同步，所有的认证信息、插件信息、选择器信息、规则信息和元数据信息。主要是通过<code>eventPublisher</code>发布同步事件。这里就跟前面提到的同步逻辑就又联系起来了，<code>eventPublisher</code>通过<code>publishEvent()</code>发布完事件后，有<code>ApplicationListener</code>执行事件变更操作，在<code>ShenYu</code>中就是前面提到的<code>DataChangedEventDispatcher</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SyncDataServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 事件发布</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApplicationEventPublisher</span><span class="token plain"> eventPublisher</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">/***</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 全量数据同步</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param type the type</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">syncAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步认证信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        appAuthService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">syncData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步插件信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> pluginDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pluginService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> ruleDataList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ruleService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RULE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleDataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步元数据信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        metaDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">syncData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-网关同步操作初始化">5. 网关同步操作初始化<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#5-%E7%BD%91%E5%85%B3%E5%90%8C%E6%AD%A5%E6%93%8D%E4%BD%9C%E5%88%9D%E5%A7%8B%E5%8C%96" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>网关这边的数据同步初始化操作主要是订阅<code>zk</code>中的节点，当有数据变更时，收到变更数据。这依赖于<code>ZooKeeper</code>的<code>Watch</code>机制。在<code>ShenYu</code>中，负责<code>zk</code>数据同步的是<code>ZookeeperSyncDataService</code>，也在前面提到过。</p>
<p><code>ZookeeperSyncDataService</code>的功能逻辑是在实例化的过程中完成的：对<code>zk</code>中的<code>shenyu</code>数据同步节点完成订阅。这里的订阅分两类，一类是已经存在的节点上面数据发生更新，这通过<code>zkClient.subscribeDataChanges()</code>方法实现；另一类是当前节点下有新增或删除节点，即子节点发生变化，这通过<code>zkClient.subscribeChildChanges()</code>方法实现。</p>
<p><code>ZookeeperSyncDataService</code>的代码有点多，这里我们以插件数据的读取和订阅进行追踪，其他类型的数据操作原理是一样的。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *  zookeeper 数据同步服务</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ZookeeperSyncDataService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">SyncDataService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">AutoCloseable</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 在实例化的时候，完成从zk中读取数据的操作，并订阅节点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ZookeeperSyncDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">/*省略构造参数参数*/</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">zkClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> zkClient</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">pluginDataSubscriber </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pluginDataSubscriber</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">metaDataSubscribers </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> metaDataSubscribers</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">authDataSubscribers </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> authDataSubscribers</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅插件、选择器和规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">watcherData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅认证数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">watchAppAuth</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">watchMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">watcherData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 插件节点路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginParent </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PLUGIN_PARENT</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 所有插件节点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> pluginZKs </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">zkClientGetChildren</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginParent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> pluginName </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> pluginZKs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅当前所有插件、选择器和规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">watcherAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅子节点（新增或删除一个插件）</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        zkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">subscribeChildChanges</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginParent</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">parentPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> currentChildren</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">currentChildren</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> pluginName </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> currentChildren</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 需要订阅子节点的所有插件、选择器和规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token function" style="color:#d73a49">watcherAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">watcherAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅插件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">watcherPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅选择器数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">watcherSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅规则数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">watcherRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">watcherPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 当前插件路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> pluginPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DefaultPathConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildPluginPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 是否存在，不存在就创建</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">zkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            zkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createPersistent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 读取zk上当前节点数据，并反序列化</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PluginData</span><span class="token plain"> pluginData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> zkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">readData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> zkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">readData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 缓存到网关内存中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">cachePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅插件节点</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">subscribePluginDataChanges</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">cachePluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token plain"> pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       </span><span class="token comment" style="color:#999988;font-style:italic">// 省略实现逻辑，其实就是 CommonPluginDataSubscriber 中的操作，跟前面都能联系起来</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">subscribePluginDataChanges</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 订阅数据变更：更新或删除</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        zkClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">subscribeDataChanges</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">IZkDataListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleDataChange</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> dataPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                 </span><span class="token comment" style="color:#999988;font-style:italic">// 省略实现逻辑，其实就是 CommonPluginDataSubscriber 中的操作，跟前面都能联系起来</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleDataDeleted</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> dataPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 删除操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  </span><span class="token comment" style="color:#999988;font-style:italic">// 省略实现逻辑，其实就是 CommonPluginDataSubscriber 中的操作，跟前面都能联系起来</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">    </span><br></span></code></pre></div></div>
<p>上面的源代码中都给出了注释，相信大家可以看明白。订阅插件数据的主要逻辑如下：</p>
<blockquote>
<ol>
<li class="">构造当前插件路径</li>
<li class="">路径是否存在，不存在就创建</li>
<li class="">读取zk上当前节点数据，并反序列化</li>
<li class="">插件数据缓存到网关内存中</li>
<li class="">订阅插件节点</li>
</ol>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-总结">6. 总结<a href="https://shenyu.apache.org/zh/blog/DataSync-SourceCode-Analysis-ZooKeeper-Data-Sync#6-%E6%80%BB%E7%BB%93" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>本文通过一个实际案例，对<code>zookeeper</code>的数据同步原理进行了源码分析。涉及到的主要知识点如下：</p>
<ul>
<li class="">基于<code>zookeeper</code>的数据同步，主要是通过<code>watch</code>机制实现；</li>
<li class="">通过<code>Spring</code>完成事件发布和监听；</li>
<li class="">通过抽象<code>DataChangedListener</code>接口，支持多种同步策略，面向接口编程；</li>
<li class="">使用单例设计模式实现缓存数据类<code>BaseDataCache</code>；</li>
<li class="">通过<code>SpringBoot</code>的条件装配和<code>starter</code>加载机制实现配置类的加载。</li>
</ul>]]></content>
        <author>
            <name>midnight2104</name>
            <uri>https://github.com/midnight2104</uri>
        </author>
        <category label="zookeeper" term="zookeeper"/>
        <category label="data sync" term="data sync"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[e2e测试详解]]></title>
        <id>https://shenyu.apache.org/zh/blog/E2eTest-Analysis</id>
        <link href="https://shenyu.apache.org/zh/blog/E2eTest-Analysis"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[这篇文章将会对Apache ShenYu的e2e模块进行深入剖析。]]></summary>
        <content type="html"><![CDATA[<p>这篇文章将会对Apache ShenYu的e2e模块进行深入剖析。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="什么是e2e">什么是e2e<a href="https://shenyu.apache.org/zh/blog/E2eTest-Analysis#%E4%BB%80%E4%B9%88%E6%98%AFe2e" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>e2e(end to end)，也叫端到端测试，是一种用于测试应用程序流是否从头到尾按设计执行的方法。 执行端到端测试的目的是识别系统依赖关系，并确保在各种系统组件和系统之间传递正确的信息。端到端测试的目的是测试 整个软件的依赖性、数据完整性以及与其他系统、接口和数据库的通信，以模拟完整的生产场景。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="e2e的优势">e2e的优势<a href="https://shenyu.apache.org/zh/blog/E2eTest-Analysis#e2e%E7%9A%84%E4%BC%98%E5%8A%BF" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>e2e测试能够模拟真实用户场景下测试软件系统的完整性和准确性，能够验证整个系统是否按照预期工作，以及不同组件是否能够协同工作。 e2e测试有以下几个好处:</p>
<ol>
<li class="">帮助保证系统功能的正确性：e2e测试能够模拟真实用户场景下的交互和操作，验证整个系统是否能够按照预期工作，帮助发现系统中的潜在问题和缺陷。</li>
<li class="">提高测试覆盖率：e2e测试能够覆盖整个系统，包括前端、后端、数据库等不同层面和组件，从而提高测试覆盖率，保证测试的全面性和准确性。</li>
<li class="">保证系统的稳定性：E2E测试可以检查系统在各种情况下的稳定性和健壮性，包括系统的响应时间、错误处理能力、并发性等方面，帮助确保系统在面对高负载和异常情况时仍然能够保持稳定运行。</li>
<li class="">减少测试成本：e2e测试能够提高测试效率和准确性，减少测试成本和时间，从而帮助企业更快速地发布和交付高质量的软件产品。</li>
</ol>
<p>总之，e2e测试是一种全面的测试方式，能够验证整个系统是否按照预期工作，提高测试覆盖率和测试效率，从而保证系统的稳定性和正确性，减少测试成本和时间，是一种非常重要和有效的测试方法，所以我们需要完善 e2e相关代码。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="自动化e2e测试如何实现">自动化e2e测试如何实现<a href="https://shenyu.apache.org/zh/blog/E2eTest-Analysis#%E8%87%AA%E5%8A%A8%E5%8C%96e2e%E6%B5%8B%E8%AF%95%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>在Apache ShenYu中，e2e测试的主要步骤体现在GitHub Action工作流的脚本中，如下所示，该脚本位于 <a href="https://github.com/apache/incubator-shenyu/tree/master/.github/workflows" target="_blank" rel="noopener noreferrer" class="">~/.github/workflows</a>目录下的e2e文件中。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> e2e</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">pull_request</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">push</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">branches</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> master</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">jobs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">changes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">build-docker-images</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">e2e-http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">e2e-case</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">runs-on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">needs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> changes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> build</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">docker</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">images</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">if</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> needs.changes.outputs.e2e == 'true' </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">strategy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">matrix</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">case</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu-e2e-case-spring-cloud"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu-e2e-case-apache-dubbo"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu-e2e-case-sofa"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">steps</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> actions/checkout@v3</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">submodules</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Load ShenYu Docker Images</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          docker load --input /tmp/apache-shenyu-admin.tar</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          docker load --input /tmp/apache-shenyu-bootstrap.tar</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          docker image ls -a</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Build examples with Maven</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ./mvnw </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">B clean install </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Pexample </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Dmaven.javadoc.skip=true </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Dmaven.test.skip=true </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">f ./shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">examples/pom.xml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Run ShenYu E2E Tests</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">storage</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> mysql</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          bash ./shenyu-e2e/script/storage_init.sh</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          ./mvnw -B -f ./shenyu-e2e/pom.xml -pl shenyu-e2e-case/${{ matrix.case }} -Dstorage=mysql test</span><br></span></code></pre></div></div>
<p>当工作流触发时，使用shenyu-dist模块下的dockerfile文件构建admin与bootstrap项目的镜像并上传，当e2e测试模块运行时可以加载admin与bootstrap镜像。紧接着构建examples中的模块，最后执行对应测试模块的测试方法。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="本地如何运行e2e测试">本地如何运行e2e测试<a href="https://shenyu.apache.org/zh/blog/E2eTest-Analysis#%E6%9C%AC%E5%9C%B0%E5%A6%82%E4%BD%95%E8%BF%90%E8%A1%8Ce2e%E6%B5%8B%E8%AF%95" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>如果需要编写e2e测试用例，首先需要在本地编码并调试。目前e2e支持两种启动方式，一个是docker启动，另一个是host启动。这两种模式可以通过在测试类中的@ShenYuTest注解中切换。host启动方式直接在本地将需要启动的服务直接启动即可运行测试代码。采用docker进行启动前，需要在先构建出相应镜像。因为ShenYu目前需要支持在github工作流进行e2e测试，建议采用docker启动方式。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="e2e启动流程剖析">e2e启动流程剖析<a href="https://shenyu.apache.org/zh/blog/E2eTest-Analysis#e2e%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B%E5%89%96%E6%9E%90" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>目前e2e模块主要分为四个部分，分别为：case、client、common以及engine。</p>
<p><img decoding="async" loading="lazy" alt="e2e-modules" src="https://shenyu.apache.org/zh/assets/images/e2e-modules-1ff1ff840f0fe5a53970e750624f61b6.png" width="595" height="200" class="img_ev3q"></p>
<p>case模块存放插件的测试用例，client模块编写了admin与gateway的客户端，以便请求对应接口。common存放一些公共类，engine模块是框架的核心，依托testcontainer框架利用java代码启动docker容器并完成对admin以及gatewat的配置操作。</p>
<p>接下来我将依托源码对e2e启动流程进行剖析。</p>
<p>当我们执行case中的测试方法时，@ShenYuTest注解将会生效，对测试类进行扩展。通过@ShenYuTest，我们可以选择启动方法、对admin以及gateway配置相关参数，以及选择将要执行的docker-compose文件。对于admin以及gateway，可以配置登陆所需的用户名、密码、数据同步方式以及修改yaml的内容。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@ShenYuTest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        mode </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenYuEngineConfigure</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">Mode</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DOCKER</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        services </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token annotation punctuation" style="color:#393A34">@ShenYuTest.ServiceConfigure</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        serviceName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"admin"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        port </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">9095</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        baseUrl </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"http://{hostname:localhost}:9095"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        parameters </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token annotation punctuation" style="color:#393A34">@ShenYuTest.Parameter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"username"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"admin"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token annotation punctuation" style="color:#393A34">@ShenYuTest.Parameter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"password"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"123456"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token annotation punctuation" style="color:#393A34">@ShenYuTest.Parameter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"dataSyn"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"admin_websocket"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token annotation punctuation" style="color:#393A34">@ShenYuTest.ServiceConfigure</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        serviceName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"gateway"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        port </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">9195</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        baseUrl </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"http://{hostname:localhost}:9195"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        type </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenYuEngineConfigure</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">ServiceType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SHENYU_GATEWAY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        parameters </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                          </span><span class="token annotation punctuation" style="color:#393A34">@ShenYuTest.Parameter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"application"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain">  </span><span class="token string" style="color:#e3116c">"spring.cloud.discovery.enabled:true,eureka.client.enabled:true"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                          </span><span class="token annotation punctuation" style="color:#393A34">@ShenYuTest.Parameter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"dataSyn"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"gateway_websocket"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">           dockerComposeFile </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"classpath:./docker-compose.mysql.yml"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>@ShenYuTest通过ShenYuExtension类进行扩展，对admin与gateway的配置在ShenYuExtension中的beforeAll中生效。具体的生效逻辑在DockerServiceCompose类中实现。</p>
<p><img decoding="async" loading="lazy" alt="e2e-shenyutest" src="https://shenyu.apache.org/zh/assets/images/e2e-shenyutest-8ea26c9ea373d2c182be8d19c53cb021.png" width="1180" height="342" class="img_ev3q"></p>
<p><img decoding="async" loading="lazy" alt="e2e-beforeall" src="https://shenyu.apache.org/zh/assets/images/e2e-beforeall-51fdb9d49dbc3eae99f77268b0e1a5c9.png" width="1794" height="546" class="img_ev3q"></p>
<p>@ShenYuTest配置项在docker启动前生效，主要通过修改测试模块中resource目录下的yaml文件。目前e2e支持对不同数据同步方式进行测试，其原理就是通过DockerServiceCompose类中的chooseDataSyn方法。在DataSyncHandler中对各种数据同步方式需要修改的内容进行初始化，最后启动container。</p>
<p><img decoding="async" loading="lazy" alt="e2e-docer-service-compose" src="https://shenyu.apache.org/zh/assets/images/e2e-docer-service-compose-ac329d9290f48407e5c8310031913fb2.png" width="1846" height="680" class="img_ev3q"></p>
<p><img decoding="async" loading="lazy" alt="e2e-datahandle-syn" src="https://shenyu.apache.org/zh/assets/images/e2e-datahandle-syn-92a7b3dc57bc8b46972128042b8281cb.png" width="1656" height="1054" class="img_ev3q"></p>
<p>当docker启动完后，开始对插件功能进行测试。在PluginsTest类中，有针对测试进行的前置以及后置操作。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@BeforeAll</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">AdminClient</span><span class="token plain"> adminClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">GatewayClient</span><span class="token plain"> gatewayClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">InterruptedException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">JsonProcessingException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        adminClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">login</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Thread</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sleep</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">10000</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorDTOList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> adminClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAllSelectors</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaDataDTOList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> adminClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAllMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> ruleDTOList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> adminClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAllRules</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Assertions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">assertEquals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorDTOList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Assertions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">assertEquals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">13</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaDataDTOList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Assertions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">assertEquals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">14</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleDTOList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> selectorDTOList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">SpringCloudPluginCases</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">verifierUri</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaDataCacheList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> gatewayClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMetaDataCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorCacheData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorCacheList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> gatewayClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSelectorCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleCacheData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> ruleCacheList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> gatewayClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRuleCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Assertions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">assertEquals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorCacheList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Assertions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">assertEquals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">13</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaDataCacheList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Assertions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">assertEquals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">14</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleCacheList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">MultiValueMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> formData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">LinkedMultiValueMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        formData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"id"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"8"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        formData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"name"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"springCloud"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        formData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"enabled"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"true"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        formData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"role"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Proxy"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        formData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"sort"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"200"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        adminClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">changePluginStatus</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"8"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> formData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> selectorDTOList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        adminClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">deleteSelectors</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorDTOList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> adminClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listAllSelectors</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Assertions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">assertEquals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorDTOList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>以springcloud插件为例，首先需要测试注册中心以及数据同步能否正常工作，接着启动插件并删除已存在的选择器。测试数据是否成功注册进注册中心，可以调用admin客户端的接口进行测试，测试数据同步是否成功，可以获取gateway的缓存进行测试。</p>
<p>接着运行case文件中的测试用例，通过@ShenYuScenario获取用例。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ShenYuScenario</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">provider </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SpringCloudPluginCases</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">testSpringCloud</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">GatewayClient</span><span class="token plain"> gateway</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">CaseSpec</span><span class="token plain"> spec</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        spec</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getVerifiers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">verifier </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> verifier</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">verify</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">gateway</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHttpRequesterSupplier</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>针对不同的插件，我们可以构建Case类，存放要测试的规则。所有的测试规则存放进list中，按顺序进行测试。beforeEachSpec中进行构建选择器与规则，caseSpec存放测试实体，如果符合uri规则的应存在，否则不存在。我们需要模拟用户对选择器和规则进行新增，因为各个插件的选择器的handler规则不一定相同，所以我们需要根据插件需求去编写其handle类。并通过请求验证其符合规则。具体测试用例主要分为两大类，一类是对uri规则进行匹配，比如euqal、path_pattern、start_with、end_with，一类是请求类型，比如get、put、post、delete。</p>
<p>当八种匹配情况都测试通过后，可以判断该插件功能正常，我们在测试结束后需要恢复环境，将所有的选择器删除，将该插件设置为不可用，最后关闭所有容器。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ScenarioSpec</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Lists</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newArrayList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token function" style="color:#d73a49">testWithUriEquals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token function" style="color:#d73a49">testWithUriPathPattern</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token function" style="color:#d73a49">testWithUriStartWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token function" style="color:#d73a49">testWithEndWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token function" style="color:#d73a49">testWithMethodGet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token function" style="color:#d73a49">testWithMethodPost</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token function" style="color:#d73a49">testWithMethodPut</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token function" style="color:#d73a49">testWithMethodDelete</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">ShenYuScenarioSpec</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">testWithUriEquals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenYuScenarioSpec</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"single-spring-cloud uri =]"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">beforeEachSpec</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token class-name">ShenYuBeforeEachSpec</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addSelectorAndRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                        </span><span class="token function" style="color:#d73a49">newSelectorBuilder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"selector"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Plugin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SPRING_CLOUD</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">                                               </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SpringCloudSelectorHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">serviceId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"springCloud-test"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">gray</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">divideUpstreams</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">DIVIDE_UPSTREAMS</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">conditionList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">newConditions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Condition</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">ParamType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Condition</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">Operator</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">EQUAL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">TEST</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                        </span><span class="token function" style="color:#d73a49">newRuleBuilder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"rule"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">                               </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SpringCloudRuleHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">loadBalance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"hash"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">timeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">3000</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">conditionList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">newConditions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Condition</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">ParamType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Condition</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">Operator</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">EQUAL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">TEST</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">checker</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">notExists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">TEST</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">waiting</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">exists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">TEST</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">caseSpec</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token class-name">ShenYuCaseSpec</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addExists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">TEST</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addNotExists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/springcloud/te"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addNotExists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/put"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addNotExists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/get"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">afterEachSpec</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenYuAfterEachSpec</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DEFAULT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>]]></content>
        <author>
            <name>Haiqi Qin</name>
            <uri>https://github.com/HaiqiQin</uri>
        </author>
        <category label="E2e Test" term="E2e Test"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[集成测试剖析]]></title>
        <id>https://shenyu.apache.org/zh/blog/IntegrationTest-Analysis</id>
        <link href="https://shenyu.apache.org/zh/blog/IntegrationTest-Analysis"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[这篇文章将会对Apache ShenYu的集成测试进行深入剖析。]]></summary>
        <content type="html"><![CDATA[<p>这篇文章将会对Apache ShenYu的集成测试进行深入剖析。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="什么是集成测试">什么是集成测试？<a href="https://shenyu.apache.org/zh/blog/IntegrationTest-Analysis#%E4%BB%80%E4%B9%88%E6%98%AF%E9%9B%86%E6%88%90%E6%B5%8B%E8%AF%95" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>集成测试在一些项目里也叫E2E (End To End)测试，主要用于测试各个模块组装成一个系统后是否能符合预期。</p>
<p>Apache ShenYu将集成测试放在了持续集成中，利用GitHub Action，在每次向主分支提交Pull Request或是Merge时触发。这样可以大大降低项目的维护成本，提升Apache ShenYu的稳定性。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="自动化的集成测试如何实现">自动化的集成测试如何实现？<a href="https://shenyu.apache.org/zh/blog/IntegrationTest-Analysis#%E8%87%AA%E5%8A%A8%E5%8C%96%E7%9A%84%E9%9B%86%E6%88%90%E6%B5%8B%E8%AF%95%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>Apache ShenYu中，集成测试的主要步骤体现在GitHub Action工作流的脚本中，如下所示，该脚本位于 <a href="https://github.com/apache/incubator-shenyu/tree/master/.github/workflows" target="_blank" rel="noopener noreferrer" class="">~/.github/workflows</a>目录下。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> it</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">pull_request</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">push</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">branches</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> master</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">jobs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">build</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">strategy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">matrix</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">case</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">integrated</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">test</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">alibaba</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">dubbo</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">runs-on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">steps</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> actions/checkout@v2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">submodules</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">...</span><br></span></code></pre></div></div>
<p>下面我将从这个yaml文件出发，带你剖析整个自动化集成测试的流程。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="工作流的触发">工作流的触发<a href="https://shenyu.apache.org/zh/blog/IntegrationTest-Analysis#%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%9A%84%E8%A7%A6%E5%8F%91" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>由于我们在 <code>on</code> 中指定了 <code>pull_request</code> 和 <code>push.branch: master</code>，那么当我们提交pull_request或是merge分支到master（push）的时候，就会触发这个工作流。</p>
<p>关于更多GitHub Action的用法，可以参考 <a href="https://docs.github.com/en/actions" target="_blank" rel="noopener noreferrer" class="">GitHub Action</a> 的文档，这里不会做详细的介绍。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="初始化环境">初始化环境<a href="https://shenyu.apache.org/zh/blog/IntegrationTest-Analysis#%E5%88%9D%E5%A7%8B%E5%8C%96%E7%8E%AF%E5%A2%83" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<ul>
<li class="">拉取代码</li>
</ul>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> actions/checkout@v2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> 	    </span><span class="token key atrule" style="color:#00a4db">submodules</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><br></span></code></pre></div></div>
<ul>
<li class="">设置跳过标志</li>
</ul>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Set Skip Env Var</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ./.github/actions/skip</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">ci</span><br></span></code></pre></div></div>
<p>当发生的是一些对功能无关的改动（如改动文档）时，会跳过集成测试，以节约资源。</p>
<ul>
<li class="">缓存maven依赖、安装Java</li>
</ul>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Cache Maven Repos</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> actions/setup</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">java@v1</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="构建整个项目同时构建docker镜像">构建整个项目，同时构建docker镜像<a href="https://shenyu.apache.org/zh/blog/IntegrationTest-Analysis#%E6%9E%84%E5%BB%BA%E6%95%B4%E4%B8%AA%E9%A1%B9%E7%9B%AE%E5%90%8C%E6%97%B6%E6%9E%84%E5%BB%BAdocker%E9%95%9C%E5%83%8F" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">./mvnw -B clean install -Prelease,docker -Dmaven.javadoc.skip=true -Dmaven.test.skip=true</span><br></span></code></pre></div></div>
<p>上面这行命令中，-P后面跟着<code>release,docker</code>，表示会激活pom文件中相关的profile配置。</p>
<p>而release和docker这两个profile，目前只在 <code>shenyu-dist</code> 下的几个子模块中存在。下面将以 <a href="https://github.com/apache/incubator-shenyu/tree/master/shenyu-dist/shenyu-admin-dist" target="_blank" rel="noopener noreferrer" class="">shenyu-dist-admin</a> 模块为例，介绍profile为release和docker的配置的具体内容。另外，集成测试只使用了这一步构建的 <code>shenyu-admin</code> 镜像。</p>
<ul>
<li class="">
<p>首先是release</p>
<div class="language-xml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-xml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">profile</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">release</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">activation</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">activeByDefault</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">false</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">activeByDefault</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">activation</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">build</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">finalName</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">apache-shenyu-incubating-${project.version}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">finalName</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">plugins</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">plugin</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">groupId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">org.apache.maven.plugins</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">groupId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">artifactId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">maven-assembly-plugin</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">artifactId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">executions</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">execution</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">admin-bin</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">phase</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">package</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">phase</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">goals</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">goal</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">single</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">goal</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">goals</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">execution</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">executions</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">configuration</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">descriptors</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">descriptor</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">${project.basedir}/src/main/assembly/binary.xml</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">descriptor</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">descriptors</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">tarLongFileMode</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">posix</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">tarLongFileMode</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">configuration</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">plugin</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">plugins</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">build</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">profile</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<p>当-P后面跟着release时，就会激活上面的 <code>maven-assembly-plugin</code> 插件。而executions中将插件的执行时机绑定在了maven生命周期package中，这也就意味着，当我们执行 <code>mvn install</code> 的时候就会触发。</p>
<p>configuration中指定了我们编写好的 <code>binary.xml</code>，<code>maven-assembly-plugin</code> 插件将会按照这个文件，将需要的文件复制进来，并打包。你可以点击链接查看该文件：<a href="https://github.com/apache/incubator-shenyu/blob/master/shenyu-dist/shenyu-admin-dist/src/main/assembly/binary.xml" target="_blank" rel="noopener noreferrer" class="">shenyu-dist/shenyu-admin-dist/src/main/assembly/binary.xml</a></p>
<p>根据这个文件，插件会将其他模块下打包好的jar包、配置文件、启动脚本等“复制”过来，最终打成 <code>tar.gz</code> 格式的压缩包。</p>
</li>
<li class="">
<p>然后是docker</p>
<div class="language-xml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-xml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">profile</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">docker</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">activation</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">activeByDefault</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">false</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">activeByDefault</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">activation</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">build</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">plugins</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">plugin</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">groupId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">com.spotify</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">groupId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">artifactId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">dockerfile-maven-plugin</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">artifactId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">version</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">${dockerfile-maven-plugin.version}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">version</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">executions</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">execution</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">tag-latest</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">goals</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">goal</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">build</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">goal</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">goals</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">configuration</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">tag</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">latest</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">tag</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">configuration</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">execution</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">execution</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">tag-version</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">goals</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">goal</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">build</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">goal</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">goals</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">configuration</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">tag</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">${project.version}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">tag</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">configuration</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">execution</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">executions</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">configuration</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">repository</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">apache/shenyu-admin</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">repository</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">buildArgs</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">APP_NAME</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">apache-shenyu-incubating-${project.version}-admin-bin</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">APP_NAME</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">buildArgs</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">configuration</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">plugin</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">plugins</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">build</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">profile</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<p>类比上面的release，这里是激活 <code>dockerfile-maven-plugin</code> 插件。当 <code>mvn install -Pdocker</code> 时，插件就会利用我们编写好的dockerfile构建docker镜像。</p>
</li>
</ul>
<p>需要注意的是，dockerfile-maven-plugin目前对aarch64架构的设备支持有限，在aarch64架构的机器上运行该插件时会出现如下错误。且在本人写这篇文章的时候已经很久没有维护，这意味着aarch64架构的设备使用这个插件的问题在短期内不会解决。</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">[ERROR] Failed to execute goal com.spotify:dockerfile-maven-plugin:1.4.6:build (tag-latest) on project shenyu-admin-dist: Could not build image: java.util.concurrent.ExecutionException: com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException: java.lang.UnsatisfiedLinkError: could not load FFI provider jnr.ffi.provider.jffi.Provider: ExceptionInInitializerError: Can't overwrite cause with java.lang.UnsatisfiedLinkError: java.lang.UnsatisfiedLinkError: /private/var/folders/w2/j27f16yj7cvf_1cxbgqb89vh0000gn/T/jffi4972193792308935312.dylib: dlopen(/private/var/folders/w2/j27f16yj7cvf_1cxbgqb89vh0000gn/T/jffi4972193792308935312.dylib, 1): no suitable image found.  Did find:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[ERROR]         /private/var/folders/w2/j27f16yj7cvf_1cxbgqb89vh0000gn/T/jffi4972193792308935312.dylib: no matching architecture in universal wrapper</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">[ERROR]         /private/var/folders/w2/j27f16yj7cvf_1cxbgqb89vh0000gn/T/jffi4972193792308935312.dylib: no matching architecture in universal wrapper</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">...</span><br></span></code></pre></div></div>
<p>这里有个临时的解决方案：</p>
<ol>
<li class="">
<p>打开一个新的shell，输入如下命令，利用 socat 将 unix socket 路由到 tcp 端口</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">socat TCP-LISTEN:2375,range=127.0.0.1/32,reuseaddr,fork UNIX-CLIENT:/var/run/docker.sock</span><br></span></code></pre></div></div>
</li>
<li class="">
<p>设置环境变量</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">export DOCKER_HOST=tcp://127.0.0.1:2375</span><br></span></code></pre></div></div>
</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="构建examples模块">构建examples模块<a href="https://shenyu.apache.org/zh/blog/IntegrationTest-Analysis#%E6%9E%84%E5%BB%BAexamples%E6%A8%A1%E5%9D%97" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Build examples</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">if</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> env.SKIP_CI </span><span class="token tag" style="color:#00009f">!=</span><span class="token plain"> 'true'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ./mvnw </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">B clean install </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Pexample </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Dmaven.javadoc.skip=true </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Dmaven.test.skip=true </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">f ./shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">examples/pom.xml</span><br></span></code></pre></div></div>
<p>因为考虑到release的需要，目前项目根目录下的pom文件中不饱含example子模块，所以上面这个步骤另外构建了examples模块。</p>
<p>与上面类似，这行命令也会利用maven的插件构建镜像，以供我们后续docker编排使用。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="构建定制化网关">构建定制化网关<a href="https://shenyu.apache.org/zh/blog/IntegrationTest-Analysis#%E6%9E%84%E5%BB%BA%E5%AE%9A%E5%88%B6%E5%8C%96%E7%BD%91%E5%85%B3" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Build integrated tests</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">if</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> env.SKIP_CI </span><span class="token tag" style="color:#00009f">!=</span><span class="token plain"> 'true'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ./mvnw </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">B clean install </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Pit </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">DskipTests </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">f ./shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">integrated</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">test/pom.xml</span><br></span></code></pre></div></div>
<p>为了细分Apache ShenYu的不同功能的集成测试，我们在这一步将构建集成测试模块定制的网关。所谓的“定制”就是在pom文件中引入需要的最少依赖，然后代替默认的 <code>shenyu-bootstrap</code>。与上面两个步骤类似，这一步也会构建出docker镜像。</p>
<p>值得注意的是，这里的打包构建的方式与 <code>shenyu-dist</code> 模块的有一些不同，你可以通过对比pom文件发现。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="运行docker-compose">运行docker compose<a href="https://shenyu.apache.org/zh/blog/IntegrationTest-Analysis#%E8%BF%90%E8%A1%8Cdocker-compose" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Start docker compose</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">if</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> env.SKIP_CI </span><span class="token tag" style="color:#00009f">!=</span><span class="token plain"> 'true'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> docker</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">compose </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">f ./shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">integrated</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">test/$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> matrix.case </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">/docker</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">compose.yml up </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">d</span><br></span></code></pre></div></div>
<p>这一步将会根据集成测试模块下编写好的不同的 <code>docker-compose.yml</code> 文件，进行docker编排。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">version</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"3.9"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">services</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">shenyu-zk</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">container_name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">zk</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> zookeeper</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">3.5</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">shenyu-redis</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> redis</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">6.0</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">alpine</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">container_name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">redis</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">shenyu-examples-http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">deploy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">resources</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">limits</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">memory</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 2048M</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">container_name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">examples</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">http</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">examples</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">shenyu-admin</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> apache/shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">admin</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">container_name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">admin</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">shenyu-integrated-test-http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">container_name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">integrated</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">test</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">http</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> apache/shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">integrated</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">test</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">depends_on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">shenyu-admin</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">condition</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> service_healthy</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">healthcheck</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">test</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"CMD"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"wget"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"http://shenyu-integrated-test-http:9195/actuator/health"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">timeout</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 2s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">retries</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">networks</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> shenyu</span><br></span></code></pre></div></div>
<p>例如 <code>shenyu-integrated-test-http</code> 模块下的 <code>docker-compose.yml</code>，按顺序启动了zookeeper、redis、example、admin、网关等服务。其中，example、admin、网关的镜像是我们之前构建的。</p>
<p>其中，docker-compose利用 <code>depends_on</code> 确定了服务之间的拓扑关系，并且大部分服务都有相应的健康检查，待健康检查通过后才会启动下一个服务。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="运行健康检查等待docker-compose启动完毕">运行健康检查，等待docker-compose启动完毕<a href="https://shenyu.apache.org/zh/blog/IntegrationTest-Analysis#%E8%BF%90%E8%A1%8C%E5%81%A5%E5%BA%B7%E6%A3%80%E6%9F%A5%E7%AD%89%E5%BE%85docker-compose%E5%90%AF%E5%8A%A8%E5%AE%8C%E6%AF%95" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Wait for docker compose start up completely</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">if</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> env.SKIP_CI </span><span class="token tag" style="color:#00009f">!=</span><span class="token plain"> 'true'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> bash ./shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">integrated</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">test/$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> matrix.case </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">/script/healthcheck.sh</span><br></span></code></pre></div></div>
<p>在这一步，宿主机会运行 <code>healthcheck.sh</code> 这个脚本，然后利用 curl 命令访问各个服务列表（在services.list文件中）的健康状态接口 <code>/actuator/health</code>，一直到服务状态都为正常才会继续。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="运行测试">运行测试<a href="https://shenyu.apache.org/zh/blog/IntegrationTest-Analysis#%E8%BF%90%E8%A1%8C%E6%B5%8B%E8%AF%95" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Run test</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> test</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">if</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> env.SKIP_CI </span><span class="token tag" style="color:#00009f">!=</span><span class="token plain"> 'true'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ./mvnw test </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">Pit </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">f ./shenyu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">integrated</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">test/$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> matrix.case </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">/pom.xml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">continue-on-error</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><br></span></code></pre></div></div>
<p>这一步就是利用maven test命令，逐个执行 <code>/src/test/</code>  目录下的测试类。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="查看docker-compose日志">查看Docker Compose日志<a href="https://shenyu.apache.org/zh/blog/IntegrationTest-Analysis#%E6%9F%A5%E7%9C%8Bdocker-compose%E6%97%A5%E5%BF%97" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Check test result</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">if</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> env.SKIP_CI </span><span class="token tag" style="color:#00009f">!=</span><span class="token plain"> 'true'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">    docker-compose -f ./shenyu-integrated-test/${{ matrix.case }}/docker-compose.yml logs --tail="all"</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">    if [[ ${{steps.test.outcome}} == "failure" ]]; then</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">      echo "Test Failed"</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">      exit 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">    else</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">      echo "Test Successful"</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">      exit 0</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">    fi</span><br></span></code></pre></div></div>
<p>当工作流出现错误时，docker compose的日志可以帮助我们更好的排查问题，所以在这一步我们将docker compose的日志打印出来。</p>]]></content>
        <author>
            <name>Kunshuai Zhu</name>
            <uri>https://github.com/JooKS-me</uri>
        </author>
        <category label="Integration Test" term="Integration Test"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[扩展插件加载逻辑]]></title>
        <id>https://shenyu.apache.org/zh/blog/Loader-SourceCode-Analysis-ExtLoader</id>
        <link href="https://shenyu.apache.org/zh/blog/Loader-SourceCode-Analysis-ExtLoader"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[本文基于shenyu-2.6.1版本进行源码分析.]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p>本文基于<code>shenyu-2.6.1</code>版本进行源码分析.</p>
</blockquote>
<p>Shenyu 提供了一种机制来定制自己的插件或是修改已有的插件，在其内部通过extPlugin的配置实现，其需要满足以下两点：</p>
<ol>
<li class="">实现接口 <code>ShenyuPlugin</code> 或是 <code>PluginDataHandler</code></li>
<li class="">将实现的包打包后，放置于<code>shenyu.extPlugin.path</code>对应的路径下</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="入口">入口<a href="https://shenyu.apache.org/zh/blog/Loader-SourceCode-Analysis-ExtLoader#%E5%85%A5%E5%8F%A3" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>真正实现该逻辑的类是<code>ShenyuLoaderService</code>,接下来看下该类是如何处理</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuLoaderService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuWebHandler</span><span class="token plain"> webHandler</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">CommonPluginDataSubscriber</span><span class="token plain"> subscriber</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuConfig</span><span class="token plain"> shenyuConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 插件信息的信息订阅</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">subscriber </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> subscriber</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// Shenyu封装的WebHandler，包含了所有的插件逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">webHandler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> webHandler</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 配置信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">shenyuConfig </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> shenyuConfig</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 扩展插件的配置信息，如路径，是否启用、开启多少线程来处理、检查加载的频率等信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ExtPlugin</span><span class="token plain"> config </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> shenyuConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getExtPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果启用的，则创建定时任务来检查并加载</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEnabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 创建一个指定线程名称的定时任务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ScheduledThreadPoolExecutor</span><span class="token plain"> executor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ScheduledThreadPoolExecutor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getThreads</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuThreadFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"plugin-ext-loader"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 创建固定频率执行的任务，默认在30s，每300s，执行一次</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            executor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">scheduleAtFixedRate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">loadExtOrUploadPlugins</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getScheduleDelay</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getScheduleTime</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SECONDS</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span></code></pre></div></div>
<p>该类有以下几个属性：</p>
<p><code>webHandler</code>: 该类是shenyu 处理请求的入口，引用了所有的插件数据，在扩展插件加载后，需要进行更新</p>
<p><code>subscriber</code>: 该类是插件的订阅的入口，引用了所有插件的订阅处理类，在扩展配置加载后，也需要进行同步更新</p>
<p><code>executor</code>: 在<code>ShenyuLoaderService</code>内部会创建一个定时任务，来定时扫描加载指定路径下的jar包，便于加载扩展的插件，实现动态发现
默认会在启动30秒后，每300秒扫描一次</p>
<p>同时这里可以通过 <code>shenyu.extPlugin.enabled</code>配置来决定是否要开启扩展插件功能的启用</p>
<p>以上的配置可以在配置文件中进行调整：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">extPlugin</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic"># 扩展插件的存储目录</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># 是否启用扩展功能</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">threads</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># 扫描加载的线程数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">scheduleTime</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">300</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># 任务执行的频率</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">scheduleDelay</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic"># 任务启动后多久开始执行</span><br></span></code></pre></div></div>
<p>接下来看下加载的逻辑：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">loadExtOrUploadPlugins</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token plain"> uploadedJarResource</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ShenyuLoaderResult</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> plugins </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ArrayList</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 获取ShenyuPluginClassloader的持有对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ShenyuPluginClassloaderHolder</span><span class="token plain"> singleton </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginClassloaderHolder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSingleton</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uploadedJarResource</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 参数为空，则从扩展的目录，加载所有的jar包</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// PluginJar：包含ShenyuPlugin接口、PluginDataHandler接口的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginJarParser</span><span class="token generics class-name punctuation" style="color:#393A34">.</span><span class="token generics class-name">PluginJar</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> uploadPluginJars </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuExtPathPluginJarLoader</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">loadExtendPlugins</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getExtPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历所有的待加载插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PluginJarParser</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">PluginJar</span><span class="token plain"> extPath </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> uploadPluginJars</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"shenyu extPlugin find new {} to load"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> extPath</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAbsolutePath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 使用扩展插件的加载器来加载指定的插件，便于后续的加载和卸载</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">ShenyuPluginClassLoader</span><span class="token plain"> extPathClassLoader </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> singleton</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createPluginClassLoader</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">extPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 使用ShenyuPluginClassLoader 进行加载</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 主要逻辑是：判断是否实现ShenyuPlugin接口、PluginDataHandler接口 或是否标识 @Component\@Service等注解，如果有，则注册为SpringBean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 构造 ShenyuLoaderResult对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    plugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">extPathClassLoader</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">loadUploadedJarPlugins</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 加载指定jar，逻辑同加载全部</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">PluginJarParser</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">PluginJar</span><span class="token plain"> pluginJar </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">PluginJarParser</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parseJar</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Base64</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getDecoder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">decode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uploadedJarResource</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPluginJar</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"shenyu upload plugin jar find new {} to load"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginJar</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getJarKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">ShenyuPluginClassLoader</span><span class="token plain"> uploadPluginClassLoader </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> singleton</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createPluginClassLoader</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginJar</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                plugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uploadPluginClassLoader</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">loadUploadedJarPlugins</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 将扩展的插件，加入到ShenyuWebHandler的插件列表，后续的请求则会经过加入的插件内容</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">loaderPlugins</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Exception</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"shenyu plugins load has error "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>该方法处理的逻辑：</p>
<ol>
<li class="">判断参数uploadedJarResource是否有值，如果没有，则会加载全部，否则加载指定资源jar包进行处理</li>
<li class="">从 <code>shenyu.extPlugin.path</code> 中获取到指定jar包，并封装成 PluginJar对象，该对象包含了jar包以下信息<!-- -->
<ul>
<li class="">version: 版本信息</li>
<li class="">groupId：包的groupId</li>
<li class="">artifactId: 包的 artifactId</li>
<li class="">absolutePath： 绝对路径</li>
<li class="">clazzMap：class对应的字节码</li>
<li class="">resourceMap：jar包的字节码</li>
</ul>
</li>
<li class="">通过<code>ShenyuPluginClassloaderHolder</code>创建对应的ClassLoader,对应的类是<code>ShenyuPluginClassLoader</code>, 并进行加载对应的类<!-- -->
<ul>
<li class="">调用<code>ShenyuPluginClassLoader.loadUploadedJarPlugins</code> 加载对应的类并注册成Spring Bean，这样可以使用Spring容器来管理</li>
</ul>
</li>
<li class="">调用<code>loaderPlugins</code>方法，将扩展的插件更新到 <code>webHandler</code> 以及 <code>subscriber</code>中</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="插件注册">插件注册<a href="https://shenyu.apache.org/zh/blog/Loader-SourceCode-Analysis-ExtLoader#%E6%8F%92%E4%BB%B6%E6%B3%A8%E5%86%8C" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>对于提供的jar包里的内容，加载器只会处理指定接口类型的类，实现逻辑在 <code>ShenyuPluginClassLoader.loadUploadedJarPlugins()</code> 方法</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ShenyuLoaderResult</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">loadUploadedJarPlugins</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ShenyuLoaderResult</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> results </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ArrayList</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 所有的类映射关系</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Set</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> names </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pluginJar</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getClazzMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">keySet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历所有的类</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        names</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">className </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Object</span><span class="token plain"> instance</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 尝试创建对象，如果可以，则加入到Spring容器中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                instance </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getOrCreateSpringBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">className</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">instance</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 构建ShenyuLoaderResult对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    results</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildResult</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">instance</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"The class successfully loaded into a upload-Jar-plugin {} is registered as a spring bean"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> className</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ClassNotFoundException</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token class-name">IllegalAccessException</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token class-name">InstantiationException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">warn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Registering upload-Jar-plugins succeeds spring bean fails:{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> className</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> results</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>该方法就是负责构建所有符合条件的对象，并封装成 <code>ShenyuLoaderResult</code>对象，该对象对于创建后对象，进行了封装，会在方法 <code>buildResult()</code>中进行处理</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">ShenyuLoaderResult</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildResult</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token plain"> instance</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuLoaderResult</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuLoaderResult</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 创建的对象是否实现了ShenyuPlugin</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">instance </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">ShenyuPlugin</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setShenyuPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuPlugin</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> instance</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 创建的对象是否实现了PluginDataHandler</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">instance </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">PluginDataHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setPluginDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PluginDataHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> instance</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>同时进入方法 <code>getOrCreateSpringBean()</code> 进一步分析</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getOrCreateSpringBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> className</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">ClassNotFoundException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">IllegalAccessException</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">InstantiationException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 确认是否已经注册过了，如果有则不处理，直接返回</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SpringBeanUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">existBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">className</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">SpringBeanUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBeanByClassName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">className</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        lock</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">lock</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Double check,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">T</span><span class="token plain"> inst </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SpringBeanUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBeanByClassName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">className</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">inst</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 使用 ShenyuPluginClassLoader 进行加载类</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> clazz </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Class</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">className</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">//Exclude ShenyuPlugin subclass and PluginDataHandler subclass</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// without adding @Component @Service annotation</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 确认是否是 ShenyuPlugin 或是 PluginDataHandler的子类</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> next </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuPlugin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isAssignableFrom</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clazz</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token class-name">PluginDataHandler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isAssignableFrom</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clazz</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">next</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果不是，确认是否标识了 @Component 与 @Service 注解</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Annotation</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> annotations </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> clazz</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAnnotations</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    next </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Arrays</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">annotations</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">anyMatch</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">annotationType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Component</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">annotationType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Service</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">next</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果符合以上内容，则注册Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">GenericBeanDefinition</span><span class="token plain"> beanDefinition </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">GenericBeanDefinition</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    beanDefinition</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setBeanClassName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">className</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    beanDefinition</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setAutowireCandidate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    beanDefinition</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setRole</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">BeanDefinition</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">ROLE_INFRASTRUCTURE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 注册bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">String</span><span class="token plain"> beanName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SpringBeanUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">registerBean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">beanDefinition</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 创建对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    inst </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SpringBeanUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBeanByClassName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">beanName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> inst</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">finally</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            lock</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unlock</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>逻辑大致如下：</p>
<ol>
<li class="">判断是否实现了接口 <code>ShenyuPlugin</code> 或 <code>PluginDataHandler</code>, 如果没有，则是否标识了 <code>@Component</code> 或是 <code>@Service</code></li>
<li class="">如果符合1的条件，则将该对象注册到Spring 容器，并返回创建的对象</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="同步">同步<a href="https://shenyu.apache.org/zh/blog/Loader-SourceCode-Analysis-ExtLoader#%E5%90%8C%E6%AD%A5" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>在插件注册成功后，这时只是实例化了插件，但它还不会生效，因为它还未添加到 Shenyu的插件链中，同步逻辑由 <code>loaderPlugins()</code>方法实现</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">loaderPlugins</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ShenyuLoaderResult</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> results</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">results</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取所有实现了接口ShenyuPlugin的对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ShenyuPlugin</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> shenyuExtendPlugins </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> results</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuLoaderResult</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">getShenyuPlugin</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步更新webHandler中plugins</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        webHandler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">putExtPlugins</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuExtendPlugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取所有实现了接口PluginDataHandler的对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginDataHandler</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> handlers </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> results</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuLoaderResult</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">getPluginDataHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 同步扩展的PluginDataHandler</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        subscriber</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">putExtendPluginDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>该方法的逻辑处理了两个数据：</p>
<ol>
<li class="">将实现了 <code>ShenyuPlugin</code> 接口的数据，同步至 <code>webHandler</code>的plugins 列表</li>
</ol>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">putExtPlugins</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ShenyuPlugin</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> extPlugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">extPlugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 过滤出新增的插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ShenyuPlugin</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> shenyuAddPlugins </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> extPlugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> plugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">noneMatch</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plugin </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> plugin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">named</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">named</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 过滤出更新的插件，以名称和旧的相同来判断，则为更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ShenyuPlugin</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> shenyuUpdatePlugins </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> extPlugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> plugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">anyMatch</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plugin </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> plugin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">named</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">named</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果没有数据，则跳过</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuAddPlugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuUpdatePlugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 复制旧的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// copy new list</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ShenyuPlugin</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> newPluginList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ArrayList</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 添加新的插件数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// Add extend plugin from pluginData or shenyu ext-lib</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">sourcePlugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuAddPlugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 添加新数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuAddPlugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            shenyuAddPlugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plugin </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"shenyu auto add extends plugins:{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plugin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">named</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            newPluginList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuAddPlugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 修改更新的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuUpdatePlugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            shenyuUpdatePlugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plugin </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"shenyu auto update extends plugins:{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> plugin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">named</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuPlugin</span><span class="token plain"> updatePlugin </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> shenyuUpdatePlugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> newPluginList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newPluginList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">named</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">updatePlugin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">named</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        newPluginList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> updatePlugin</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">sourcePlugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">sourcePlugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">named</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">updatePlugin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">named</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">sourcePlugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> updatePlugin</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 重新排序</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        plugins </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sortPlugins</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newPluginList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ol start="2">
<li class="">将实现了 <code>PluginDataHandler</code> 接口的数据，同步至 <code>subscriber</code> 的handlers 列表</li>
</ol>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">putExtendPluginDataHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">PluginDataHandler</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> handlers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历所有数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PluginDataHandler</span><span class="token plain"> handler </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> handlers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">String</span><span class="token plain"> pluginNamed </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">pluginNamed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 更新现有的PluginDataHandler列表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">MapUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">computeIfAbsent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handlerMap</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginNamed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> name </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"shenyu auto add extends plugin data handler name is :{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginNamed</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> handler</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>至此，扩展插件的加载过程分析结束。</p>]]></content>
        <author>
            <name>hql0312</name>
            <uri>https://github.com/hql0312</uri>
        </author>
        <category label="plugin" term="plugin"/>
        <category label="ext" term="ext"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Context-Path插件源码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Context-Path-Plugin</id>
        <link href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Context-Path-Plugin"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[开始前，可以参考 这篇文章 运行shenyu网关]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p>开始前，可以参考 <a class="" href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo">这篇文章</a> 运行shenyu网关</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="正文">正文<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Context-Path-Plugin#%E6%AD%A3%E6%96%87" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>首先，看<code>ContextPathPlugin#doExecute</code>方法，这是这个插件的核心。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doExecute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 1. 从JVM缓存中取得contextMappingHandle</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ContextMappingHandle</span><span class="token plain"> contextMappingHandle </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ContextPathPluginDataHandler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CACHED_HANDLE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">obtainHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CacheKeyUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INST</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 2. 根据contextMappingHandle设置shenyu上下文</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">buildContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuContext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> contextMappingHandle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ol>
<li class="">
<p>从JVM缓存中取得<code>contextMappingHandle</code></p>
<p>这里的<code>contextMappingHandle</code>是<code>ContextMappingHandle</code>类的实例，里面有两个成员变量：<code>contextPath</code>和<code>addPrefix</code></p>
<p>这两个变量在之前Admin里面的Rules表单里有出现过，是在数据同步的时候更新的。</p>
</li>
<li class="">
<p>根据contextMappingHandle设置shenyu上下文</p>
<p>下面是<code>ContextPathPlugin#buildContextPath</code>方法的源代码</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuContext</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ContextMappingHandle</span><span class="token plain"> handle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> realURI </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 1. 设置shenyu的context path，根据contextPath的长度将真实URI的前缀去掉</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNoneBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setModule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        realURI </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">substring</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">length</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 加上前缀</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNoneBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAddPrefix</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">realURI</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            realURI </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> handle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAddPrefix</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> realURI</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            realURI </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> handle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAddPrefix</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setRealUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">realURI</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">
<p>设置shenyu的context path，<strong>根据contextPath的长度将真实URI的前缀去掉</strong></p>
<p>你可能会有疑问，<strong>这里所谓的「根据contextPath的长度」会不会有问题呢？</strong></p>
<p>实际上这样的判断是没有问题的，因为请求在被Selector和Rules匹配到之后，才会被插件处理。所以在设置好Selector和Rules的前提下，是完全可以满足转换特定contextPath的需求的。</p>
</li>
</ul>
</li>
</ol>
<p>然后，<code>ContextPathPlugin</code>类还有一个比较重要的方法<code>skip</code>，下面展示了部分代码。我们可以发现：<strong>如果是对RPC服务的调用，就会直接跳过context_path插件。</strong></p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">skip</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rpcType</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DUBBO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rpcType</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">GRPC</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rpcType</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TARS</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rpcType</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">MOTAN</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rpcType</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SOFA</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>最后，context_path插件还有另一个类<code>ContextPathPluginDataHandler</code>。这个类的作用是订阅插件的数据，当插件配置被修改、删除、增加时，就往JVM缓存里面修改、删除、新增数据。</p>]]></content>
        <author>
            <name>Kunshuai Zhu</name>
            <uri>https://github.com/JooKS-me</uri>
        </author>
        <category label="Context-Path" term="Context-Path"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Divide插件源码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin</id>
        <link href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[Apache ShenYu 是一个异步的，高性能的，跨语言的，响应式的 API 网关。]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p><a href="https://shenyu.apache.org/zh/docs/index" target="_blank" rel="noopener noreferrer" class="">Apache ShenYu</a> 是一个异步的，高性能的，跨语言的，响应式的 <code>API</code> 网关。</p>
</blockquote>
<p><code>ShenYu</code> 网关使用 <code>divide</code> 插件来处理 <code>http</code> 请求。你可以查看官方文档 <a href="https://shenyu.apache.org/zh/docs/next/quick-start/quick-start-http" target="_blank" rel="noopener noreferrer" class="">Http快速开始</a> 了解如何使用该插件。</p>
<blockquote>
<p>本文基于<code>shenyu-2.4.3</code>版本进行源码分析，官网的介绍请参考 <a href="https://shenyu.apache.org/zh/docs/user-guide/proxy/http-proxy" target="_blank" rel="noopener noreferrer" class="">Http服务接入</a> 。</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-服务注册">1. 服务注册<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#1-%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="11--声明注册接口">1.1  声明注册接口<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#11--%E5%A3%B0%E6%98%8E%E6%B3%A8%E5%86%8C%E6%8E%A5%E5%8F%A3" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>使用注解<code>@ShenyuSpringMvcClient</code>将服务注册到网关。简单<code>demo</code>如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@RestController</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequestMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/order"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ShenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/order"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// API注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">OrderController</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@GetMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/findById"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ShenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/findById"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> desc </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Find by id"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 方法注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">OrderDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">findById</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@RequestParam</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"id"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hello world findById"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>注解定义：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 作用于类和方法上</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Retention</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RetentionPolicy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RUNTIME</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Target</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token class-name">ElementType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TYPE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ElementType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">METHOD</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@interface</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">//注册路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//规则名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ruleName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//描述信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">desc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//是否启用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">enabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//注册元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="12-扫描注解信息">1.2 扫描注解信息<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#12-%E6%89%AB%E6%8F%8F%E6%B3%A8%E8%A7%A3%E4%BF%A1%E6%81%AF" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>注解扫描通过<code>SpringMvcClientBeanPostProcessor</code>完成，它实现了<code>BeanPostProcessor</code>接口，是<code>Spring</code>提供的后置处理器。</p>
<p>在构造器实例化的过程中：</p>
<ul>
<li class="">读取属性配置</li>
<li class="">添加注解，读取<code>path</code>信息</li>
<li class="">启动注册中心，向<code>shenyu-admin</code>注册</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SpringMvcClientBeanPostProcessor</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">BeanPostProcessor</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 构造器实例化</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">SpringMvcClientBeanPostProcessor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PropertiesConfig</span><span class="token plain"> clientConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token plain"> shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 1. 读取属性配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Properties</span><span class="token plain"> props </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> clientConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">appName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APP_NAME</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">contextPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CONTEXT_PATH</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">appName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">String</span><span class="token plain"> errorMsg </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"http register param must config the appName or contextPath"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">errorMsg</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuClientIllegalArgumentException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">errorMsg</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">isFull </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parseBoolean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">IS_FULL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">FALSE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 2. 添加注解</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        mappingAnnotation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        mappingAnnotation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PostMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        mappingAnnotation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">GetMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        mappingAnnotation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DeleteMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        mappingAnnotation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PutMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        mappingAnnotation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RequestMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 3. 启动注册中心</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">postProcessAfterInitialization</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token plain"> bean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> beanName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">BeansException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       </span><span class="token comment" style="color:#999988;font-style:italic">// 重写后置处理器逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> bean</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span></code></pre></div></div>
<ul>
<li class="">SpringMvcClientBeanPostProcessor#postProcessAfterInitialization()</li>
</ul>
<p>重写后置处理器逻辑：读取注解信息，构建元数据对象和<code>URI</code>对象，并向<code>shenyu-admin</code>注册。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">postProcessAfterInitialization</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token plain"> bean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> beanName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">BeansException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 1. 如果是注册整个服务或者不是Controller类，就不处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">isFull</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token function" style="color:#d73a49">hasAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getClass</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Controller</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> bean</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 2. 读取类上的注解 ShenyuSpringMvcClient</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token plain"> beanShenyuClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">AnnotationUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getClass</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 2.1构建superPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> superPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildApiSuperPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getClass</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 2.2 是否注册整个类方法</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">beanShenyuClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">contains</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"*"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 构建元数据对象，然后向shenyu-admin注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildMetaDataDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">beanShenyuClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">pathJoin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> bean</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 3. 读取所有方法</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Method</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> methods </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ReflectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUniqueDeclaredMethods</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getClass</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Method</span><span class="token plain"> method </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> methods</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 3.1 读取方法上的注解 ShenyuSpringMvcClient</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token plain"> methodShenyuClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">AnnotationUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 如果方法上面没有注解，就用类上面的注解</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            methodShenyuClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">methodShenyuClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> beanShenyuClient </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> methodShenyuClient</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">methodShenyuClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">               </span><span class="token comment" style="color:#999988;font-style:italic">// 3.2 构建path信息，构建元数据对象，向shenyu-admin注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildMetaDataDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">methodShenyuClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildApiPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> bean</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">1.如果是注册整个服务或者不是<code>Controller</code>类，就不处理</li>
<li class="">2.读取类上的注解 <code>ShenyuSpringMvcClient</code>，如果是注册整个类，就在这里构建元数据对象，然后向<code>shenyu-admin</code>注册</li>
<li class="">3.处理方法上的注解 <code>ShenyuSpringMvcClient</code>，针对特定方法构建<code>path</code>信息，构建元数据对象，然后向<code>shenyu-admin</code>注册</li>
</ul>
<p>这里有两个取<code>path</code>的方法，需要特别说明一下：</p>
<ul>
<li class="">
<p>buildApiSuperPath()</p>
<p>构造<code>SuperPath</code>：先从类上的注解<code>ShenyuSpringMvcClient</code>取<code>path</code>属性，如果没有，就从当前类的<code>RequestMapping</code>注解中取<code>path</code>信息。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildApiSuperPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 先从类上的注解ShenyuSpringMvcClient取path属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token plain"> shenyuSpringMvcClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">AnnotationUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> shenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 从当前类的RequestMapping注解中取path信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RequestMapping</span><span class="token plain"> requestMapping </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">AnnotationUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">RequestMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">requestMapping</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">ArrayUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">requestMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">requestMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> requestMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">
<p>buildApiPath()</p>
<p>构建<code>path</code>：先读取方法上的注解<code>ShenyuSpringMvcClient</code>，如果存在就构建；否则从方法的其他注解上获取<code>path</code>信息；完整的<code>path = contextPath(上下文信息)+superPath(类信息)+methodPath(方法信息)</code>。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildApiPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Method</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 1. 读取方法上的注解ShenyuSpringMvcClient</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token plain"> shenyuSpringMvcClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">AnnotationUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 1.1如果存在path，就构建</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//1.2完整 path = contextPath+superPath+methodPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">pathJoin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> shenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 2.从方法的其他注解上获取path信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> path </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getPathByMethod</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">method</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">             </span><span class="token comment" style="color:#999988;font-style:italic">// 2.1 完整的path = contextPath+superPath+methodPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">pathJoin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">pathJoin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">
<p>getPathByMethod()</p>
<p>从方法的其他注解上获取<code>path</code>信息，其他注解包括：</p>
<ul>
<li class="">ShenyuSpringMvcClient</li>
<li class="">PostMapping</li>
<li class="">GetMapping</li>
<li class="">DeleteMapping</li>
<li class="">PutMapping</li>
<li class="">RequestMapping</li>
</ul>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getPathByMethod</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Method</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历接口注解获取path信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics"> </span><span class="token generics keyword" style="color:#00009f">extends</span><span class="token generics"> </span><span class="token generics class-name">Annotation</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> mapping </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> mappingAnnotation</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pathByAnnotation </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getPathByAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">AnnotationUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> mapping</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pathAttributeNames</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pathByAnnotation</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> pathByAnnotation</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>扫描注解完成后，构建元数据对象，然后将该对象发送到<code>shenyu-admin</code>，即可完成注册。</p>
<ul>
<li class="">
<p>元数据对象</p>
<p>包括当前注册方法的规则信息：contextPath，appName，注册路径，描述信息，注册类型，是否启用，规则名称和是否注册元数据。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildMetaDataDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token plain"> shenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">contextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// contextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">appName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">appName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// appName</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 注册路径，在网关规则匹配时使用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">pathDesc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">desc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 描述信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// divide插件，默认时http类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">enabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">enabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 是否启用规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ruleName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">defaultIfBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ruleName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token comment" style="color:#999988;font-style:italic">//规则名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">registerMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">registerMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//是否注册元数据信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>具体的注册逻辑由注册中心实现，在之前的文章中已经分析过了，这里就不再深入分析。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="13-注册uri信息">1.3 注册URI信息<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#13-%E6%B3%A8%E5%86%8Curi%E4%BF%A1%E6%81%AF" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p><code>ContextRegisterListener</code>负责将客户端的<code>URI</code>信息注册到<code>shenyu-admin</code>，它实现了<code>ApplicationListener</code>接口，发生上下文刷新事件<code>ContextRefreshedEvent</code>时，执行<code>onApplicationEvent()</code>方法，实现注册逻辑。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ContextRegisterListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ContextRefreshedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">BeanFactoryAware</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 构造器实例化</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ContextRegisterListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PropertiesConfig</span><span class="token plain"> clientConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 读取属性配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Properties</span><span class="token plain"> props </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> clientConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">isFull </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parseBoolean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">IS_FULL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">FALSE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">contextPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CONTEXT_PATH</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">isFull</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> errorMsg </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"http register param must config the contextPath"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">errorMsg</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuClientIllegalArgumentException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">errorMsg</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">port </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Integer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parseInt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PORT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">orElseGet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"-1"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">appName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APP_NAME</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">protocol </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PROTOCOL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">host </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HOST</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setBeanFactory</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">BeanFactory</span><span class="token plain"> beanFactory</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">BeansException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">beanFactory </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> beanFactory</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 执行应用事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ContextRefreshedEvent</span><span class="token plain"> contextRefreshedEvent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 保证该方法执行一次</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">registered</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">compareAndSet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 1. 如果是注册整个服务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">isFull</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 构建元数据，并注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildMetaDataDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 获取端口信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> mergedPort </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> port </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token class-name">PortUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findPort</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">beanFactory</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> port</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 2. 构建URI数据，并注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildURIRegisterDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">mergedPort</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"please config ${shenyu.client.http.props.port} in xml/yml !"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 构建URI数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">URIRegisterDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildURIRegisterDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> port</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">URIRegisterDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">contextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// contextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">appName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">appName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// appName</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">protocol</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">protocol</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 服务使用的协议</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">host</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">IpUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isCompleteHost</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">host</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">host </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">IpUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHost</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">host</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//主机</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">port</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">port</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 端口</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// divide插件，默认注册http类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 构建元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildMetaDataDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">contextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">appName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">appName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">enabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ruleName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="14-处理注册信息">1.4 处理注册信息<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#14-%E5%A4%84%E7%90%86%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>客户端通过注册中心注册的元数据和<code>URI</code>数据，在<code>shenyu-admin</code>进行处理，负责存储到数据库和同步给<code>shenyu</code>网关。<code>Divide</code>插件的客户端注册处理逻辑在<code>ShenyuClientRegisterDivideServiceImpl</code>中。继承关系如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/ShenyuClientRegisterDivideServiceImpl-4d9351b1efbb545cde2a3a172e35f59c.png" width="1143" height="768" class="img_ev3q"></p>
<ul>
<li class="">ShenyuClientRegisterService：客户端注册服务，顶层接口；</li>
<li class="">FallbackShenyuClientRegisterService：注册失败，提供重试操作；</li>
<li class="">AbstractShenyuClientRegisterServiceImpl：抽象类，实现部分公共注册逻辑；</li>
<li class="">AbstractContextPathRegisterService：抽象类，负责注册<code>ContextPath</code>；</li>
<li class="">ShenyuClientRegisterDivideServiceImpl：实现<code>Divide</code>插件的注册；</li>
</ul>
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="141-注册服务">1.4.1 注册服务<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#141-%E6%B3%A8%E5%86%8C%E6%9C%8D%E5%8A%A1" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h5>
<ul>
<li class="">
<p>org.apache.shenyu.admin.service.register.AbstractShenyuClientRegisterServiceImpl#register()</p>
<p>客户端通过注册中心注册的元数据<code>MetaDataRegisterDTO</code>对象在<code>shenyu-admin</code>的<code>register()</code>方法被接送到。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">register</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//1. 注册选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> selectorHandler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">selectorHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> selectorId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginNameAdapter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcTypeAdapter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//2. 注册规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> ruleHandler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ruleHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RuleDTO</span><span class="token plain"> ruleDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRpcDefaultRuleDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ruleService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//3. 注册元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">registerMetadata</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//4. 注册ContextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> contextPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">registerContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h6 class="anchor anchorTargetStickyNavbar_Vzrq" id="1411-注册选择器">1.4.1.1 注册选择器<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#1411-%E6%B3%A8%E5%86%8C%E9%80%89%E6%8B%A9%E5%99%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h6>
<ul>
<li class="">org.apache.shenyu.admin.service.impl.SelectorServiceImpl#registerDefault()</li>
</ul>
<p>构建<code>contextPath</code>，查找选择器信息是否存在，如果存在就返回<code>id</code>；不存在就创建默认的选择器信息。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建contextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> contextPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ContextPathUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAppName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 通过名称查找选择器信息是否存在</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">findByNameAndPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 不存在就创建默认的选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">
<p>默认选择器信息</p>
<p>在这里构建默认选择器信息及其条件属性。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">//注册选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//构建选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildSelectorDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selectByName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//注册默认选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">//构建选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">SelectorDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildSelectorDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//构建默认选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildDefaultSelectorDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setPluginId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic">//构建默认选择器的条件属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setSelectorConditions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildDefaultSelectorConditionDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">构建默认选择器</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">private SelectorDTO buildDefaultSelectorDTO(final String name) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    return SelectorDTO.builder()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            .name(name) // 名称</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            .type(SelectorTypeEnum.CUSTOM_FLOW.getCode()) // 默认类型自定义</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            .matchMode(MatchModeEnum.AND.getCode()) //默认匹配方式 and</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            .enabled(Boolean.TRUE)  //默认启开启</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            .loged(Boolean.TRUE)  //默认记录日志</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            .continued(Boolean.TRUE) //默认继续后续选择器</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            .sort(1) //默认顺序1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            .build();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<ul>
<li class="">构建默认选择器条件属性</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorConditionDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildDefaultSelectorConditionDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">SelectorConditionDTO</span><span class="token plain"> selectorConditionDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">SelectorConditionDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setParamType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ParamTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 默认参数类型URI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setParamName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setOperator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">OperatorEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">MATCH</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAlias</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 默认匹配策略 match</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setParamValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">AdminConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI_SUFFIX</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 默认值 /contextPath/**</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">注册默认选择器</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">@Override</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">public String registerDefault(final SelectorDTO selectorDTO) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    //选择器信息</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    SelectorDO selectorDO = SelectorDO.buildSelectorDO(selectorDTO);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    //选择器条件属性</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    List&lt;SelectorConditionDTO&gt; selectorConditionDTOs = selectorDTO.getSelectorConditions();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    if (StringUtils.isEmpty(selectorDTO.getId())) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        // 向数据库插入选择器信息</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorMapper.insertSelective(selectorDO);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          // 向数据库插入选择器条件属性</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorConditionDTOs.forEach(selectorConditionDTO -&gt; {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionDTO.setSelectorId(selectorDO.getId());        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorConditionMapper.insertSelective(SelectorConditionDO.buildSelectorConditionDO(selectorConditionDTO));</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        });</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    // 发布同步事件，向网关同步选择信息及其条件属性</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    publishEvent(selectorDO, selectorConditionDTOs);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    return selectorDO.getId();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<h6 class="anchor anchorTargetStickyNavbar_Vzrq" id="1412-注册规则">1.4.1.2 注册规则<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#1412-%E6%B3%A8%E5%86%8C%E8%A7%84%E5%88%99" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h6>
<p>在注册服务的第二步中，开始构建默认规则，然后注册规则。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">register</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//1. 注册选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//2. 注册规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 默认规则处理属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> ruleHandler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ruleHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建默认规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RuleDTO</span><span class="token plain"> ruleDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRpcDefaultRuleDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 注册规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ruleService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//3. 注册元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//4. 注册ContextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">默认规则处理属性</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ruleHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 默认规则处理属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DivideRuleHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>Divide</code>插件默认规则处理属性</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DivideRuleHandle</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">RuleHandle</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 负载均衡：默认随机</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> loadBalance </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">LoadBalanceEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RANDOM</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 重试策略：默认重试当前服务</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> retryStrategy </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RetryEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CURRENT</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 重试次数：默认3次</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> retry </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 调用超时：默认 3000</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> timeout </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TIME_OUT</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * header最大值：10240 byte</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> headerMaxSize </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HEADER_MAX_SIZE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * request最大值：102400 byte</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> requestMaxSize </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">REQUEST_MAX_SIZE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">构建默认规则信息</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 构建默认规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">RuleDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRpcDefaultRuleDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> metaDataDTO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ruleHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRuleDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleHandler</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaDataDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRuleName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaDataDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">//  构建默认规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">RuleDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRuleDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ruleHandler</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ruleName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RuleDTO</span><span class="token plain"> ruleDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RuleDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//关联的选择器id</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//规则名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">matchMode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MatchModeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">AND</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 默认匹配模式 and</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">enabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 默认开启</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">loged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//默认记录日志</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sort</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//默认顺序 1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RuleConditionDTO</span><span class="token plain"> ruleConditionDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RuleConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">paramType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ParamTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 默认参数类型URI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">paramName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">paramValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//参数值path</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">indexOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"*"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            ruleConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setOperator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">OperatorEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">MATCH</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAlias</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//如果path中有*，操作类型则默认为 match</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            ruleConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setOperator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">OperatorEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">EQ</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAlias</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 否则，默认操作类型 = </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ruleDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setRuleConditions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> ruleDTO</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.admin.service.impl.RuleServiceImpl#registerDefault()</li>
</ul>
<p>注册规则：向数据库插入记录，并向网关发布事件，进行数据同步。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RuleDTO</span><span class="token plain"> ruleDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RuleDO</span><span class="token plain"> exist </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ruleMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findBySelectorIdAndName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exist</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RuleDO</span><span class="token plain"> ruleDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RuleDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildRuleDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleConditionDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> ruleConditions </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ruleDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRuleConditions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 向数据库插入规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            ruleMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//向数据库插入规则体条件属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            ruleConditions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleConditionDTO </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                ruleConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setRuleId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">            </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                ruleConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RuleConditionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildRuleConditionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 向网关发布事件，进行数据同步</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleConditions</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> ruleDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<h6 class="anchor anchorTargetStickyNavbar_Vzrq" id="1413-�注册元数据">1.4.1.3 注册元数据<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#1413-%E6%B3%A8%E5%86%8C%E5%85%83%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h6>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">register</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//1. 注册选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//2. 注册规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//3. 注册元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">registerMetadata</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//4. 注册ContextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">
<p>org.apache.shenyu.admin.service.register.ShenyuClientRegisterDivideServiceImpl#registerMetadata()</p>
<p>插入或更新元数据，然后发布同步事件到网关。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerMetadata</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isRegisterMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 如果注册元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 获取metaDataService</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">MetaDataService</span><span class="token plain"> metaDataService </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getMetaDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据是否存在</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">MetaDataDO</span><span class="token plain"> exist </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> metaDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findByPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插入或更新元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">saveOrUpdateMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exist</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">saveOrUpdateMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataDO</span><span class="token plain"> exist</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> metaDataDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 数据类型转换 DTO-&gt;DO</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">MetaDataDO</span><span class="token plain"> metaDataDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">MetaDataTransfer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">mapRegisterDTOToEntity</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 插入数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exist</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Timestamp</span><span class="token plain"> currentTime </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Timestamp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">System</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">currentTimeMillis</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">UUIDUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">generateShortUuid</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setDateCreated</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">currentTime</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setDateUpdated</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">currentTime</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insert</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            eventType </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CREATE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 更新数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exist</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">update</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            eventType </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发布同步事件到网关</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MetaDataTransfer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">mapToData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h6 class="anchor anchorTargetStickyNavbar_Vzrq" id="1414-注册contextpath">1.4.1.4 注册ContextPath<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#1414-%E6%B3%A8%E5%86%8Ccontextpath" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h6>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">register</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//1. 注册选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//2. 注册规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//3. 注册元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//4. 注册ContextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> contextPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">registerContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.admin.service.register.AbstractContextPathRegisterService#registerContextPath()</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 设置选择器的contextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> contextPathSelectorId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getSelectorService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CONTEXT_PATH</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ContextMappingRuleHandle</span><span class="token plain"> handle </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ContextMappingRuleHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        handle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PathUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">decoratorContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 设置规则的contextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">getRuleService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildContextPathDefaultRuleDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPathSelectorId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> handle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="142-注册uri">1.4.2 注册URI<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#142-%E6%B3%A8%E5%86%8Curi" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h5>
<ul>
<li class="">org.apache.shenyu.admin.service.register.FallbackShenyuClientRegisterService#registerURI()</li>
</ul>
<p>服务端收到客户端注册的<code>URI</code>信息后，进行处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">key</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeFallBack</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 注册URI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doRegisterURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            logger</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Register success: {},{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Exception</span><span class="token plain"> ex</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            logger</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">warn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Register exception: cause:{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ex</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 注册失败后，进行重试</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addFallback</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">FallbackHolder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.admin.service.register.AbstractShenyuClientRegisterServiceImpl#doRegisterURI()</li>
</ul>
<p>从客户端注册的<code>URI</code>中获取有效的<code>URI</code>，更新对应的选择器<code>handle</code>属性，向网关发送选择器更新事件。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doRegisterURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//参数检查</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//获取选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findByNameAndPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginNameAdapter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcTypeAdapter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"doRegister Failed to execute,wait to retry."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取有效的URI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> validUriList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPort</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHost</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建选择器的handle属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> handler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">validUriList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildByName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginNameAdapter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcTypeAdapter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 向数据库更新选择器的handle属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 向网关发送选择器更新事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>关于服务注册的源码分析就以及完成了，分析流程图如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/divide-register-zh-0697d4849e6ae1dbd2f15a0fd528cd32.png" width="2077" height="821" class="img_ev3q"></p>
<p>接下来就分析<code>divide</code>插件是如何根据这些信息向<code>http</code>服务发起调用。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-服务调用">2. 服务调用<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#2-%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p><code>divide</code>插件是网关用于处理 <code>http协议</code>请求的核心处理插件。</p>
<p>以官网提供的案例 <a href="https://shenyu.apache.org/zh/docs/next/quick-start/quick-start-http" target="_blank" rel="noopener noreferrer" class="">Http快速开始</a> 为例，一个直连请求如下：</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">GET http://localhost:8189/order/findById?id=100</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Accept: application/json</span><br></span></code></pre></div></div>
<p>通过<code>ShenYu</code>网关代理后，请求如下：</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">GET http://localhost:9195/http/order/findById?id=100</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Accept: application/json</span><br></span></code></pre></div></div>
<p>通过<code>ShenYu</code>网关代理后的服务仍然能够请求到之前的服务，在这里起作用的就是<code>divide</code>插件。类继承关系如下：</p>
<p><img decoding="async" loading="lazy" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAdYAAAGoCAIAAAB0UFO8AAAACXBIWXMAAB2HAAAdhwGP5fFlAAAgAElEQVR42u2d3ZfbRJqH59/ZEzLbsJCAp+3uzhchBAwmgkzmsz07aJpZDwPj7IbgkJAYw5yFHQeyNHhgLvoqc9V3PefsXmf+o9nrLVm2VJKqSiVZsmX5+R2dnO6O7JLen97Hr0pV5R+cKkKNqU4tXVtT0W7Zwl/8Jc4ltfsDLKRd/MVf/AXBWEiK4i/+gmAspF38xV/iDIKxkBTFX/wFwVhIu/iLv8QZBGMhKUq7+AuCsZAUJc74S5xBMBaSorSLvyAYC0lR4oy/xBkE0y4pSrv4C4KxkBQlzvhLnEEw7ZKitIu/IBgLSVHijL/EGQTTLv7SLv6CYCwkRYkz/uIvCKZd/KVd/AXBWEiKEmf8BcFYSLv4i7/EGQRjISmKv/gLgrGQdvEXf4kzCMZCUpR28RcEYyEpSpzxlziDYCwkRWkXf0EwFpKixBl/iTMIxkJSlHbxd40R3EAIIbQibTSCbyGElqtOpyOX3mijOyLEBXFwcHADIVS+RK7JCKYjgr5gD8HiythGCJUvkWsgGASDYIRAMAgGwQiBYBAMgkEwQiAYBINghEAwCAbBCCEQDIJBMEIgGASDYIQQCAbBIBghEAyCQTBCCASDYBCMEAgGwSAYIQSCQfCSEbx3pXl5v3X1vVb79k7n/q7YxA/iV/FH8V8kG0IgGASXguDz15rtD3be+GTXsIkdxG6kHEIgGAQXhuCdi9uv3kyBr7yJncVL6qf24Pivf/u72A4HDlhZx9A1Gk5/fHw4HnY7DRAMgtcDwedebb5+d9eev/4mXiJeuBZ0aHR6XlqePPEZEWyHR5O+64BgFcUmI+U2EGhzqozg7njm8uOjYbvRAMEguOoIFhh940Fm/s62B1WnsKBJd3wcI6+8xRIVBE+D1hslPq4iQTs5HrkOCAbBIHhRBO9c3M5R/8Zq4cr2SHjV3NETibbHUkE3K4pBsBnBh0fH/pYEcSxEVemI6AxH3gFP+nREgODqIzhT/6+hXzj1AnU+333r4V6wXX13ZwlZEUBBVG1911F3UAx6IFiH4GQh2e70RvNPNS+qHUIHgkFwXgSfv9ZcnL/+Zh4j4XyxJ/PX3y44zZI5EpbAI7eRldogWHcvLwf28bhH6EAwCM6JYPP4s2da/xTbzCPVDA35zA1+vfSzlvj12me7Zd+QzroaTibdBgguDMG62IJgEAyCMyB470pKCXyu+9zZl0778BU/iF/N+xtmbcQQ3GzF/1JlBDc6TncwnHYfD7uuk/qEx3sA6Pr7T/pur63pkRS7tTvTbf6GXkOzFw77iYYandn+KcefeM/pXxr6KCl2SEdwsIPUF6FDcL5jiO2gjEzsZHWBzRdwEAyCy0Xw5f2WTQ9Dav0bbOINLRGs/Eu5z5Ss6zKZI8rRFNPBAFqq9lWjLwTIkmNUszYU9mtL9/7mz4+gx0D3ISSRNLJDgQjOfQxBZ/3o6IlyPEbDnSgDovskWMRZEAyCi0fwK+/vFItg8YaVQrCcdfYUlhK1F/R4ekMCpEFascdQISykfWKjCJJ8ydpQalGfhF2JCLbuiFgEwUErQTTkkIrqNS+CszkLgkFwKQhOnYicFcGG7mAZuMnncsmtjEJ4CpRJ6owpmdp+ukr3reG7xdJefkIVeYlUbelIMX9g6ChpLr8qGPGqLNZCLM5fUh6Cw5Jc2qFYBMvexW4j2u4kws2MCLYPOAgGwSUiuPPxbrEIFm9YNQRvJ4YG+zPiDCA2F866UtTwJEpikHoIlxKpyoZ0t96xNwzerSQEy8WpsqukEASbO17kY8iBYMuAg2AQXBMEJ3G8NATPStHBJDY7WbeGgLK+M/PU3Jspo1OGQrENhftL71YsgqePsyLzvG3Yl+8YlH3NMYWz4DIi2D7gIBgE16QjYrUITvYJLDLL1s98dS+t5h5WuYNlQ7pKM1bHKSlfSCeA5cTughGcFlLDPYHN4zj7gINgEFyHx3FVQLAOxLF8y5GoUnmlWdpG1R2cjwg6NiU/GMpDsPKjq2AEqz5RQDAIZlBazkFp1UFwcqhT1lm2BgSnbqkPr9IRrCJaSDHNQ8L8HREn8qoaw77bs+lGXxzBNrM8QDAIXm8Ep07NOP+rM89fmU3NED+IX3NPzagaghNjGJySq+BgpcfeggiW0RM+dkv8pewREUtDsIGGIBgErzeCt5c4QbmCCI7k8GLFab6JufkRnODjvBdC/4xubRFMFQyC64zgpS3TU28Em8eKFY7gWM9vgDDl+yj7iFNHYhWI4HzHYBNS3ag1EAyC1wbB20tcrLLSCF7sKVnqoLTCERxgS7zWfx8d4FJmcwQRKB/BmY5B4rIG3JrV2kAwCF4zBNd4yXYvjfWzMHQrSORLVHmMqmZRBafrFkaE8O5+PJz/0LOv9JMRKBXB+Y7BHFJ5WAsIBsFrjODt+n5xUVhJHR3733g2Wyir05NnamT91gzNQAV5Nu1E/na16UJrXnOWpLAkQmK6bfonjTzNt+3Gll8oE8H5jkGe/yZ9lPpfAxgZZwKCQfBaI3i7pl/fGVvkRTNKLF4m539KltZcsQg21I9mWEeH95b+OC73MUwZPTEN7+Nx3FogeKsI+QjeWjfxJfaizkoudSjPL0jyZbEu2p56sUrR1qBnM5csExGCHVJHYsTWtfE/e+RHeWUjOMcx6Bz01kubBrPiIyK20FQg+Eamy+j8tWbqxGWxg/34h8pUxE7b7XWnW3Ix7+LR35m11S2zLfNIA2UQ5hForNCIHMcQ2if38FjMoFumQLAawXRE5LiY9q40L++3rr7Xat/e6dzfFZv4Qfwq/mg5/wItsad7qV/VXqFbHIvpGytEMB0R9AXnRzACQFX/BFp4YTMQDIJBMMoNoDwjkWv5CZR7hXUQDIJBMMpZAC744Gg9TtOdeM/rFF9jGj7zrE4JDIJBMAjehM7f6PfRVaYALAnBsW+NS37PW6U+gUAwCAbBtUew9PWgmml4dT3f1AHdIBgEg2BU8gOo2YqXw6rRp0wQO1132JfWLO66TjU/e0AwCAbBCIFgEAyCEQLBIBgEg2CEQDAIBsEIgWAQDIIRQiAYBINghEAwCAbBCCEQDILLRPDBwcENhFD5ErkGgkFwHMFo7dT/6PdiIw5rKhAMgkN10BrqJ3dfExtxWFO1Wi0QDILRuurM7jO//PI1sYkfiMa6CwSDYLRmeq1/8ZdfvSY28QPRAMEgeEMRvGntVsTfWQk8RXCphTD+kkcgGAtJ0fj5BiVw2YUw/pJHIBgLSdHI+UZK4JILYfwlj0AwFpKikfONlcClFsL4Sx6BYCwkRcPzVZTAZRbC+EsegWAsJEXD81WWwOUVwvhLHoFgLCRFZ+erLYFLK4TxlzwCwVhIis7O11ACl1QI4y95BIKxkBT1zrdx4YypBC6nEMZf8ggEYyEp6p3v6zcvpfC3hEIYf8kjEIyFpOgpqxK4hEIYf8kjEIyFpOgpyxK48EIYf8kjEIyFm56iKQMhyiyE8Zc8AsFYuOkpmjoQorxCGH/JIxCMhRudoplL4EILYfwlj0AwFm50iuYogQsshPGXPALBWLi5KZqzBC6uEMZf8ggEY+HmpmjuErioQhh/ySMQjIUbmqILlcAFFcL4Sx4tD8FbRci3cAvVVMv0N9NYYN0m3gTXyN+1EAhG1fL3zPaz5u1l95yArPjXvBuukb/rgWBuZGh3vfy99IuWQLD4F3/piKAvGAtJURCMv8QZBNMuCMZf8hcEYyEpCoLxlziDYNoFwfhL/oJgLCRFQTD+EmcQTLsgGH/JXxCMhaQoCMZf8hcE0y4Ixl/yFwRjISkKgvEXBGMh7a6Nv89ffFbwV/yLvyAYBGMhKUqc8Zc4g2DaJUVpF39BMBaSosQZf4kzCKbd2qYofcEgGARjISm6svNlRAQIBsFYSIqCYPwlziAYC0Ew/pK/IBgLSVEQjL/EGQTTLgjGX/IXBGMhKQqC8Zc4g2DaBcH4S/6CYCwkRUEw/pK/IJh2QTD+kr8gGAtJURCMv+QvCKZdEIy/5C8IxkJS1Pp8WSMCBINgLCRFiTP+EmcQjIWkKO3iLwjGQlKUOOMvcQbBtFv/FKUvGASDYCwkRVd2voyIAMEgGAtJURCMv8QZBGMhCMZf8hcEYyEpCoLxlziDYNoFwfhL/oJgLCRFQTD+EmcQTLsgGH/J30ojeKsI+RZuoZqqUv5e3t8VCBb/4kst/d00gWAEgvGX/F0dgrmRoV06IvCX/KUvGAtJURCMvyAYC2m32v6yRgQIBsFYSIoSZ/wlziAYC0lR2sVfEIyFpChxxl/iDIJpt/4pSl8wCAbBWEiKrux8GREBgkEwFpKiIBh/iTMIxkIQjL/kLwjGQlIUBOMvcQbBtAuC8Zf8BcFYSIqCYPwlziCYdkEw/pK/IBgLSVEQjL/kLwimXRCMv+QvCMZCUhQE4y/5C4JpFwTjL/kLgrGQFLU+X9aIAMEgGAtJUeKMv8QZBGMhKUq7+AuCsZAUJc74S5xBMO3WP0XpCwbBIBgLSdGVnS8jIkAwCMZCUhQE4y9xBsFYCILxl/wFwVhIioJg/CXOIJh2QTD+kr8gGAtJURCMv8QZBNMuCMZf8hcEYyEpCoLxl/wFwbQLgvGX/AXBWEiKgmD8JX9BMO2CYPwlf0EwFpKi1ufLGhEgGASrLbyFEEL1UqfTWScEHxwc3EAIofWXoNn6IVgc9zZCCK2/BM2WgeBGcQLBCKG6IrhRjkAwQgitDsF0RCCE0Mo6IkAwQgiBYIQQAsEgGCGEQDBCCIFgEIwQAsEgGCGEQDAIRgiBYBCMEEIgeGEEN5ut5r8NWsPvFNu9w2YHpiOEQHAZCG7ttD7+Rg3f2Lb/Oy4IhBAILhLBVvCVttpb3h4c//Vvfxfb4cAhAQgsoQvUaDj98fHheNjtNEAwCM5y6XR6/fFkNN1Srx5IkT22x4cnT/ygBdvh0aTvOgRWRbHZpRjfBgJtTpWvye545vLjo2G7sSQK1xbBd0afL4Lg8xcurmMRYXMRQwp7mnTHxzHyylssUQnsNGi9UeLjKhK0k+OR64DgmiPY7b336ZffLoLg4OXrUXccPZEu8UnXePUs53IXR9V2h6OjJyO3Udm4GY4wHtWjY6mgmxXFINiM4MOjY39LgjgWoqp0RHTE9XDs3d/QEbEIgls7OwKgiyP4o0+/SA2f8/nuWw/3gu3quzsruW58IgTXupl6y7ncg1Yqi2DzEQb/K6q2vuuoOygGPRCsQ3CykGx3eqP5p5oX1Q6hqymCH/zXo0IQLLZz586b+PvFnsxff7vgNFdy9zQlxYzFj8c9ELzIEcolsP3xg2AzgmOBla9SEFwfBDdbLZ+eSgQ3733z1N7l081L8nbWvaVD8Mf/+dAQO5+5wa+XftYSv177bHd1V/zs+o6VGCA4M4LnNxapvTogOBOCdbEFwfVB8O9u3tYh+Ow7gxh8g+3pV64rEWzuEY4huNmK/2UZV7w7ka9dm0s5uY/33Mkd+g+y+26vndYRJu7Bu4Oh3zEqbsZjj7nbHUds3RBwjv+XtrSb1w/r/zFIQvGerrfF8rYh3sqdj/cYDLuubYq24wfZsD/CohDsHfzsGLwjT33C4xsxSjMiGb1plGYN9RMNNRLx10Qs/p7TvzT0l4Fih3QEBztIhYLuus13DInrRxGZ2MnqApsv4BuN4ACdMQQ3P/rvWc37TnSO3IM/n77wsq4KFtvVV9uWCFb+peSKI172huzQP9KVL3fdQ//DsbaEGR09MYwNCD4SlFtQb0aPoSe/Z7iPOzlUtqV6pB6h2GByeKI9SJsjjDxTsq7LUgM7PXItVfsqI8QxJ0cZZm0o7NfW91DFIChdWuoPIYmkkR0KRHDuYwgKheS16l88wTUQC4juk2ARZ0HwDMFP7bwo+PvCuw8y9QWL7eD3/eoiuBPv/G1Y9EXI15M0Cif+5DqZQjK8xPvLD7sXQHCvH82TJATDZ+snClLruhrlF2ZF8HbGcX6Gk4odttIXDxaJkzUMccnaUGpRn4RdiQi27ohYBMFBK/LlGro8zo3gbM6C4BDBfgmc9XGceVyEDNzkc7nktpzezNSSR4bLtOCNPtZ3wxIymg9S8eLG7hYjYwNsOiLCa3qaGNP5SP4+sx4Dv7nkPKXw7JKfEPKjnsRBeuPP5qW9XVdJBIuPjzLMeQnSVbpvDd8t5ot82JGXSNWWjhTB8StpLr8q+KxVf3SZPssLRrDSwWIRLHsXu42QL+8cCLYPOAguDMGf/OnraiJYd4Ga785i15Pyoglv06R30N275Xscl34MDXUHn6HMVx72Ig8MVTW1CcTmwllXihq673UnKzdk+SzRbF8yFCUhWC5OlXVDIQg2VyHyMeRAcFEPb0GwLYLvf/6lTRxXgGB9UplLHmnEa8ptaSQny0FwjqtW+c4Nu9EgWcdsKHuWdWsIGCp03RGmfl7GHreW0VC4v/RuxSJ4+oEamedtw758x6Dsa9YlSFYE2wccBGsQ/ODPWRF8886DaiLYwNkQl6orJsfDmUT94hSG4Iz3bo1IB0JDUYlYTy21HzaXfAKTb5ZtOII72UuriYNyB8uGdJVm7HyVlC+kE8ByYnfBCO6kj45f5HFc1mQEwTMEP/1jVyD4qZ0Xk8x97tc3DQj+effXFURwyrNgYyFgM3BNeY0G15nfN9o3gtgSweYnXf4cYm9E2pFioZwIglUcKQrBOhDHXpgjUaXySrO0jao7OB8RdGxKfjCUh2DdaJYiEWxxJYDgEhH84ItHunHBp3dno4Cf/dUfmve+aX706OzBh/5ICXlcWgzBzVarggiOdDvOZ+LLm6FTMjeClcVg7GleUQhOXSLHpjOxWAQnhzplnWVrQHDqlvrwKh3BKqKFFNM8JMzfEXEir6ox7Lu9bsbpQvmOIfflDYKLQfAbb143zI5LTo1LdlDEEGwZx2UiOPmYaPGbPvuOZn/xxhiIDbV2PgSHvXUe5f0Enj2gM48DyTGfOGvaRMcwOCVXwcFKj70FESzbmuzij+9Z2oiIpSHY1MUPgktdI8KA4OkcjUdPd34hWCw28cP27T8Z+oL33XeqiGCpW1ZZAscK4az3y7ZVqvScyjB2NQeCLfuyV1IFG45wEQRnmpibH8EJPs57IfTP6NYWwVTBK0Nw9ze/LWqZHvs4LhPBlnmre+Rl83LLS0pXDy6IYMvXKvuCy3gcVx6Cs44zWZwIcs9vgDDl+yj7iBU9y6UhON8x2IQ0a2qA4MzrBX/68JvFEdxx3qoggm3G3JiTxDzCZttipFSmgiIHgk2DPTRrmNmHpWAEL/aULFOoCyFCuLTpwPHfRxexlNkcmlHYZSA40zFIl70G3JrV2kBwkQj2lwxeBMG3Ph5tV1L25V5ql6VuOoBy1GSjo16LRPcA2rLOzfq/hkHy6eOdO7ZH6KWxfhaGbgWJfIkqR1vzieh03cKIEN7dj4fzH3pZr7TI9LMyEZzvGMwhlR/zguASv7joxZeuLILgyiow26b30Hy/nJxoEH3cH00td+I9444tUu5qK45IhTKbcxxOeLPtC5bGMKWOCYtNUB5FlsXyHiHG0thwhNIo42P/G8/awfxpuQc847dmaAYqyLNpJ/Kyc9NB0F5zWbuSLOfmpE0OVE/zDUxfBoLzHYM8/036KFU8SQbBfH1nvgdxlrfbaatSqZc9MyNVuamqacX4UMvHUIYhH14empZa7430Y0XiCNYfYWyRF827TXTrV2R+SpbWXLEINtSPZlhHh/eW/jgu9zFMGT0xXQY8jlsqggcP7fnbfP3HVUZwajeuTdUcW3kvuUaicgKucuk/8xyN5MqW9iMBlOOC/THI5j5c3WKVXj3rOhmO0DV9Po1US8Qu1kXbUy9WmbjzKIQI9vdSsXVtZo5Lj/LKRnCOY9A56A1wnAaTERFLRbBQc+9866NHKcXvfm97UzWdhDZdMb3jpPYvB2urp+4c3k17++dZ1lo+sOx3DI7lcZqP0OsEd+fLyXecsr9YN2t4F+nOsn90GQSz3VnZd6DkO4bQPrmHJ/tcyvK0EQgOWfzyay3331sfjj3s3vmq9YdR86fuNkIb9YmbfT2NmqlS36q1WQhGCFX/a/3KvudbZGGzdUXwVhECwQgtDKA8I5Fr+QmUb4X1shG8VY5AMEKVKAAXeXC0NqfpTvynxImvMQ2feVakBF4egumIQGhlSPI6f6PfRzeu88Nn5Zccxr7nrTqfQPQFI7QJCH6i+7bA2p9v6oBuEAyCESq3/6E/W/FyWCn6lAxip+uv9z9fszjfyEgQDIIRQrUVCEYIIRAMghFCIBgEI4QQCAbBCCEQDIIRQggEg2CEEAiuBIIPDg5uIITQ+kvQbP0QjFDZev/el2IjDmg5WicEdxAqX2+OnoiNOKDlqNVqrQ2CTyFUsp49d+36d/8Qm/iBaKD1EghGa6+XP/yf69//n9jED0QDgeAVI1h5SrRbuCri76wEniK41EIYf8kjEIyFpGj8fIMSuOxCGH/JIxCMhaRo5HwjJXDJhTD+kkcgGAtJ0cj5xkrgUgth/CWPQDAWkqLh+SpK4DILYfwlj0AwFpKi4fkqS+DyCmH8JY9AMBaSorPz1ZbApRXC+EsegWAsJEVn52sogUsqhPGXPALBWEiKeuf7/KXrphK4nEIYf8kjEIyFpKh3vlcH/5vC3xIKYfwlj0AwFpKip6xK4BIKYfwlj0AwFpKipyxL4MILYfwlj0AwFm56iqYMhCizEMZf8ggEY+Gmp2jqQIjyCmH8JY9AMBZudIpmLoELLYTxlzwCwVi40SmaowQusBDGX/IIBGPh5qZozhK4uEIYf8kjEIyFm5uiuUvgogph/CWPQDAWbmiKLlQCF1QI4y95BIKxcENTdMESuJBCGH/JIxCMhRuaok+/cOHpxkV/e671ktiCX/3t4m//IiAr/o39PbK9cAF/yV8QjIWkaPHne+5fHwoEi3/xFwSDYCwkRUEw/hLnBRC8VYR8C7dQTVUpfy+8/ZVAsPgXX2rp76YJBCMQjL/k7+oQzI0M7dIRgb/kL33BWEiKgmD8BcFYSLsgGH/JIxCMhaQoCAbBIBgLaRcE4y9xBsFYSIqCYBAMgrGQFAXB+EucQTAWgmD8BcEgGAtJURCMv8QZBNMuCMZf8hcEYyEpCoLxlziDYNoFwfhL/oJgLCRFQTD+EmcQTLsgGH/JXxCMhaQoCMZf8hcE0y4Ixl/yFwRjISkKgvEXBGMh7YJg/CWPQDAWkqIgGASDYCykXRCMv+QRCMZCUhQEg2AQjIWkKAjGX+IMgrEQBINgEAyCsZAUBcH4S5xBMBaCYPwlf0EwFpKiIBh/iTMIpl0QjL/kLwjGQlIUBOMvcQbBtAuC8Zf8BcFYSIqCYPwlf0Ew7YJg/CV/QTAWkqIgGH/JXxBMuyAYf8lfEIyFpCgIxl8QjIW0C4LxlzwCwVhIioJgEAyCsZB2QTD+EmcQjIWkKAgGwXVE8FYR8i3cQjVVpfy98PZXAsHiX3yppb+bJhCMQDD+kr+rQzA3MrRLRwT+kr/0BWMhKQqC8RcEYyHtgmD8JY9AMBaSoiAYBINgLKRdEIy/xBkEYyEpCoJBMAjGQlIUBOMvcQbBWAiC8RcEg2AsJEVBMP4SZxBMuyAYf8lfEIyFpCgIxl/iDIJpFwTjL/kLgrGQFAXB+EucQTDtgmD8JX9BMBaSoiAYf8lfEEy7IBh/yV8QjIWkKAjGXxCMhbQLgvGXPALBWEiKgmAQDIKxkHZBMP6SRyAYC0lREAyCQTAWkqIgGH+JMwjGQhAMgkEwCMZCUhQE4y9xBsFYCILxl/wFwVhIioJg/CXOIJh2QTD+kr8gGAtJURCMv8QZBNMuCMZf8hcEYyEpCoLxl/wFwbS77v6eefHngr/iX/wFwSC4hhbeQggVoU6nA4JBcB4EHxwc3EAI5ZXIIBAMgvMjWFxD2wihvBIZBIJBMAhGCASDYBCMEAgGwSAYBCMEgkEwCEYIBIPgOYIbKCoQjFCxCIYqBoFgEIwQCF4dgumIoCMCIToi6AsGwQiBYBAMgkEwQiAYBINghEAwCAbBCCEQDIKrj+Ar7eZ+r/nesHl73Lo/EZv4wft1vyf+i7REIBgEg+BSENy89tPmB39qffIXwyZ2ELuRnAgEg2AQXByCL15u3fyjGb6R7eYfxUs2IQkbDac/Pj4cD7udxkrep+FO/vq3v4vt8bi3kgi0B8f+ARwOnBoYAYJBcPUQ/Oq11t2vM/DX3+5+LV5YeXpORupt2HWddiM9mbvjJzMCHg1t9i/8fQpEsCkgA4E2p8oILsoIEAyCK4Zgwd8H32Xmr789+K7KFG40eqOTWd7qtsdHk77rbAyCUwLy+OR4lIgGCAbBILg0BF+8nKf+jdXCVe2RsEFwAGLd7W2jMxwdHR8KUi/YEZH3fUpC8KF3MN6WjEYMtVXpiCjICBAMgiuE4Gz9v4Z+4TQ5n+++9XAv2K6+u7NMBCfrJnFL3u70+uNjuQBcZm6vFsHJgIhojI6eKENREQTzOA4E1w3BzWs/LYC//jAJ4xgJ54s9mb/+dsFprhDBUm3V62vQs1EInvUUB6GQ2gLBIBgEl4Ng/fiz5vC7swcfbrV/8tS5K6daF09feu3pN35xtne3NfxeN1LN0JDP3ODXSz9riV+vfbZbBQT76FlJP2PVEOzf7B/6O5xMuvMdQDAIBsElIPhKW8ff7btfb71yXZA3uT3jdLWv0s/aiCG42Yr/ZbUIjhWAIzfZZTHd5u/Q6Mz+Yn7D+KsSf1ER0Om6Q3/ARn8+YMMGwd6nyOyFk77ba+v6tVMRHOwg3RDoEDyPg+l0UndInu+0V0QRKF0AlQYp3xYEg+AKIbi539PVv1uvvCVo+89Xromyd/vOI/HHH9159Hzv7vQv97SF837PEsHKv6wWwRHSRXdOAij4i4GJQVkdAN1cSzakrtjY+AQzgv3RsqoHjIrxswUiODfVj0IAAAYoSURBVPjQkutlzVspdshxvroAyn+f3tAcq962AYJBcMUQ/P4nSpKe+c0Hgr8/fPnN5v1v4/+r6YWYIfj9T9YbwSr6KDNfebeeSh8DgoM3nNMzMlBBVHM6BHsgk14YG+GQPLwCOyIWQXD8fE+sztcCwWG3vheKaBP5evlBMAguDcGajmC/C+L53w8zP5HTdwfLwE0+l0tuK0Kwui9CgWB9r0WsoJZhob2dlwaKxUrXthtFVRRJ8mEI+sg9HkElmHhJSkDCAl/aoVgEG893YjjfVATPHXGUH1H5etJBMAguC8Gtj79VkvT0nvf8TVECp24ff7vWCFb2HmgBZOwc8N/HcmiXuVtDLhgtkRTlY+QYUkZESG2lRyAvggs/XxnByU/E1FsWEAyC64/gJI7XHsGGu+zgvywIouv9SGW0uadVV4krAxIMkc7EvnwItjnfcHRKRgSbR9rl64sAwSB4NR0RLxTaEVE/BOt2lvfX/T0CsqBGM4x2UFXcqS9U7mA3Yzsxa6NABOc9X8vHcfa2gmAQXNXHcW/f8oZDvPRG89438WFnd75q3jvM8ThuLRBs3xdsIqMeTOYODcOQWyW2pNJPtw6RqXa2XyCiYATbnC8IBsGbPCit9cn3P7zieNMxLrbP/vaONyht+P2Pbo+fe/s/Tp+/Kmrk5v1J1kFpa4LglL7LxGM0BYMCXCZxoHwfm1kPZgRbLH8h9zmE/QDyonF9t2dYAbJABFudLwgGwZuAYNPUjDuPfvjym8qpGf/ykwPd0DTLL9SoLoKtxwUb+hz8vyi7Hc0INtAhbxUcrELZUyA4yyTAMhBsOl8QDII3AsHGCcqiFj7z9i1R8z6199JTu5dPX379metvv9D/bMGO4Moi2DDOzGY8rw+LkEqq5vJXwSok5Zs0XB0EUwWDYBC8vGV6qo/gcCCt3cMoJYYCIitTPcfgNtOIiFwLRxSIYN3YO/NosNznC4JBcA0RvL3ExSori+DIRAbrDoQkCkV6z3sh1FVhyogIHcg0q5elDkpbGoJT56eoR0RkPF8QDILrieANWbJdOxnMHcqL5NpXr6pRwMNZRayp71JBJl6YPEh5xYPYO5tfOPt0cZ3yEKzrPY8NvYh9SOQ+XxAMguuI4O2N+OKi6AAAbzuMrhFjMzPCnOGPp4sS5HifyHww6cs7GtEV5Q2zjecvlItrpzvwJvtmnaCc7cg1U43j86pjE5Tzni8IBsE1RfB2jb++0+qLiw41VaRlhgfFoBltNiMr1EPKXMMyPRHYKV5eJoINRz69pdB2lbSliNmfLwgGwfVF8HY9v8TegGCvaPWW1k1fTDYdwWmr9ti8j9wlEvtsSFmsMlE8hhAc9NoZV0rLdeST2MfA4+nXu5l7q5Pn662XNjCdLwgGwbVG8HyMhHGk2mz8mf34B5TtM6PjtN1e15sokfn7Kdqd6Qunr13+F39MV0n3Wm9nWYdBeb42M+iWJhAMgpeK4JmutJv7veZ7w+btcev+RGziB+/X/Z7l/AuEcstm+gYIBsG1RjBCK+s7WmhhMxAMgkEwQgWUwIt/VykIBsEgGKFEnetOvOd1iQeh8nPFipTAIBgEg2BUQwTHvjUu+T1vVegFBsEgGASjOiLYOJZZnqwBgtcMwVtFyEfwVi0EglGFQex03WFfWrO4665gLF1WBG8hvUAwCEYIBK8OwXRE0BGBEB0R9AWDYIRAMAgGwSAYIRAMgkEwQiAYBINghBAIBsEgGCEQDII3AcEHBwc3EEJ5JTIIBIPg/AhGCC0uEAyC86iDECpCrVYLBINghFBFBYJBMEIIBINgLKx2u/iLv8QZBGMhKUq7+AuCsZAUJc74S5xBMBaSorSLvyAYC0lR4oy/xBkE0y4pSrv4C4KxkBQlzvhLnEEw7ZKitIu/IBgLSVHijL/EGQTTLv7SLv6CYCwkRYkz/uIvCKZd/KVd/AXBWEiKEmf8BcFYSLv4i7/EGQRjISmKv/gLgrGQdvEXf4kzCMZCUpR28RcEYyEpSpzxlziDYCwkRWkXf0EwFpKixBl/iTMIJkVJUdrFXxCMhaQoccZf4gyCaZcUpV38BcFYSIoSZ/wlziCYdvGXdvG3su3+P1nK/SpJ8iNQAAAAAElFTkSuQmCC" width="470" height="424" class="img_ev3q"></p>
<ul>
<li class="">ShenyuPlugin：顶层接口，定义接口方法；</li>
<li class="">AbstractShenyuPlugin：抽象类，实现插件共有逻辑；</li>
<li class="">DividePlugin：Divide插件。</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="21-接收请求">2.1 接收请求<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#21-%E6%8E%A5%E6%94%B6%E8%AF%B7%E6%B1%82" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>通过<code>ShenYu</code>网关代理后，请求入口是<code>ShenyuWebHandler</code>，它实现了<code>org.springframework.web.server.WebHandler</code>接口。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">public final class ShenyuWebHandler implements WebHandler, ApplicationListener&lt;SortPluginEvent&gt; {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    //......</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    /**</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     * 处理web请求</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     */</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    @Override</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    public Mono&lt;Void&gt; handle(@NonNull final ServerWebExchange exchange) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       // 执行默认插件链</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        Mono&lt;Void&gt; execute = new DefaultShenyuPluginChain(plugins).execute(exchange);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        if (scheduled) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            return execute.subscribeOn(scheduler);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        return execute;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    private static class DefaultShenyuPluginChain implements ShenyuPluginChain {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        private int index;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        private final List&lt;ShenyuPlugin&gt; plugins;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        /**</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         * 实例化默认插件链</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         */</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        DefaultShenyuPluginChain(final List&lt;ShenyuPlugin&gt; plugins) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            this.plugins = plugins;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        /**</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         * 执行每个插件.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         */</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        @Override</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        public Mono&lt;Void&gt; execute(final ServerWebExchange exchange) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            return Mono.defer(() -&gt; {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                if (this.index &lt; plugins.size()) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    // 获取当前执行插件</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    ShenyuPlugin plugin = plugins.get(this.index++);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    // 是否跳过当前插件</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    boolean skip = plugin.skip(exchange);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    if (skip) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        // 如果跳过就执行下一个</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        return this.execute(exchange);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    // 执行当前插件</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    return plugin.execute(exchange, this);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                return Mono.empty();</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            });</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="22-匹配规则">2.2 匹配规则<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#22-%E5%8C%B9%E9%85%8D%E8%A7%84%E5%88%99" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">org.apache.shenyu.plugin.base.AbstractShenyuPlugin#execute()</li>
</ul>
<p>在<code>execute()</code>方法中执行选择器和规则的匹配逻辑。</p>
<ul>
<li class="">匹配选择器；</li>
<li class="">匹配规则；</li>
<li class="">执行插件。</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 插件名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> pluginName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">named</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 插件信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PluginData</span><span class="token plain"> pluginData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">obtainPluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> pluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEnabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectors </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">obtainSelectorData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectors</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleSelectorIfNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 匹配选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">matchSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectors</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleSelectorIfNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">selectorLog</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> rules </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">obtainRuleData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rules</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleRuleIfNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 匹配规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">RuleData</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">SelectorTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">FULL_FLOW</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">//get last</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                rule </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> rules</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rules</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                rule </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">matchRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> rules</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleRuleIfNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">ruleLog</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rule</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 执行插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doExecute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="23-执行divide插件">2.3 执行divide插件<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#23-%E6%89%A7%E8%A1%8Cdivide%E6%8F%92%E4%BB%B6" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">org.apache.shenyu.plugin.divide.DividePlugin#doExecute()</li>
</ul>
<p>在<code>doExecute()</code>方法中执行<code>divide</code>插件的具体逻辑：</p>
<ul>
<li class="">校验<code>header</code>大小；</li>
<li class="">校验<code>request</code>大小；</li>
<li class="">获取服务列表；</li>
<li class="">实现负载均衡；</li>
<li class="">设置请求<code>url</code>，超时时间，重试策略。</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doExecute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取上下文信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuContext</span><span class="token plain"> shenyuContext </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CONTEXT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">assert</span><span class="token plain"> shenyuContext </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取规则的handle属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">DivideRuleHandle</span><span class="token plain"> ruleHandle </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DividePluginDataHandler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CACHED_HANDLE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">obtainHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CacheKeyUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INST</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> headerSize </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 校验header大小</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> multiHeader </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">values</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> value </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> multiHeader</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                headerSize </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> value</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">length</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">headerSize </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> ruleHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHeaderMaxSize</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"request header is too large"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Object</span><span class="token plain"> error </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuResultWrap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">REQUEST_HEADER_TOO_LARGE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">WebFluxResultUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">result</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 校验request大小</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContentLength</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> ruleHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequestMaxSize</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"request entity is too large"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Object</span><span class="token plain"> error </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuResultWrap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">REQUEST_ENTITY_TOO_LARGE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">WebFluxResultUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">result</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取服务列表upstreamList</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Upstream</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> upstreamList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">UpstreamCacheManager</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findUpstreamListBySelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstreamList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"divide upstream configuration error： {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Object</span><span class="token plain"> error </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuResultWrap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CANNOT_FIND_HEALTHY_UPSTREAM_URL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">WebFluxResultUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">result</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 请求ip</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> ip </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">requireNonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRemoteAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHostAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 实现负载均衡</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Upstream</span><span class="token plain"> upstream </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">LoadBalancerFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstreamList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLoadBalance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstream</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"divide has no upstream"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Object</span><span class="token plain"> error </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuResultWrap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CANNOT_FIND_HEALTHY_UPSTREAM_URL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">WebFluxResultUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">result</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 设置url</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> domain </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> upstream</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildDomain</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP_DOMAIN</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> domain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 设置超时时间</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP_TIME_OUT</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP_RETRY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRetry</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 设置重试策略</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RETRY_STRATEGY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRetryStrategy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">LOAD_BALANCE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLoadBalance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DIVIDE_SELECTOR_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-发起请求">2.4 发起请求<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#24-%E5%8F%91%E8%B5%B7%E8%AF%B7%E6%B1%82" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>默认由<code>WebClientPlugin</code>向<code>http</code>服务发起调用请求，类继承关系如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/WebClientPlugin-64ae237cda7fd819160795669ee2e2bd.png" width="918" height="433" class="img_ev3q"></p>
<ul>
<li class="">ShenyuPlugin：顶层插件，定义插件方法；</li>
<li class="">AbstractHttpClientPlugin：抽象类，实现请求调用的公共逻辑；</li>
<li class="">WebClientPlugin：通过<code>WebClient</code>发起请求；</li>
<li class="">NettyHttpClientPlugin：通过<code>Netty</code>发起请求。</li>
</ul>
<p>发起请求调用：</p>
<ul>
<li class="">org.apache.shenyu.plugin.httpclient.AbstractHttpClientPlugin#execute()</li>
</ul>
<p>在<code>execute()</code>方法中发起请求调用：</p>
<ul>
<li class="">获取指定的超时时间，重试次数</li>
<li class="">发起请求</li>
<li class="">根据指定的重试策略进行失败后重试操作</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractHttpClientPlugin</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ShenyuPlugin</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Logger</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">LoggerFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLogger</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">AbstractHttpClientPlugin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取上下文信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuContext</span><span class="token plain"> shenyuContext </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CONTEXT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">assert</span><span class="token plain"> shenyuContext </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取uri</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">URI</span><span class="token plain"> uri </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP_URI</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Object</span><span class="token plain"> error </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuResultWrap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CANNOT_FIND_URL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">WebFluxResultUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">result</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取指定的超时时间</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> timeout </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">long</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP_TIME_OUT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">orElse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">3000L</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Duration</span><span class="token plain"> duration </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Duration</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofMillis</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">timeout</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取指定重试次数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> retryTimes </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP_RETRY</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">orElse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取指定的重试策略</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> retryStrategy </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RETRY_STRATEGY</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">orElseGet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RetryEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CURRENT</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"The request urlPath is {}, retryTimes is {}, retryStrategy is {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uri</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toASCIIString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> retryTimes</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> retryStrategy</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建header</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpHeaders</span><span class="token plain"> httpHeaders </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildHttpHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发起请求</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> response </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMethodValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uri</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> httpHeaders</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBody</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">timeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">duration</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">TimeoutException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Response took longer than timeout: "</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> duration</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doOnError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 重试策略CURRENT，对当前服务进行重试</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RetryEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CURRENT</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">retryStrategy</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//old version of DividePlugin and SpringCloudPlugin will run on this</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> response</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">retryWhen</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Retry</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">anyOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">TimeoutException</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ConnectTimeoutException</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ReadTimeoutException</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">IllegalStateException</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">retryMax</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">retryTimes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">backoff</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Backoff</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exponential</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Duration</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofMillis</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">200</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Duration</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofSeconds</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onErrorMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">TimeoutException</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> th </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ResponseStatusException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">GATEWAY_TIMEOUT</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> th</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> th</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flatMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Function</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Object</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics"> </span><span class="token generics keyword" style="color:#00009f">extends</span><span class="token generics"> </span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> o </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 对其他服务进行重试</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 排除已经调用过的服务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Set</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics">URI</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> exclude </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Sets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newHashSet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 请求重试</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">resend</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">response</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> duration</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> httpHeaders</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exclude</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> retryTimes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onErrorMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">TimeoutException</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> th </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ResponseStatusException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">GATEWAY_TIMEOUT</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> th</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> th</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flatMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Function</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Object</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics"> </span><span class="token generics keyword" style="color:#00009f">extends</span><span class="token generics"> </span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> o </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">resend</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> clientResponse</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                           </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                           </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Duration</span><span class="token plain"> duration</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                           </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpHeaders</span><span class="token plain"> httpHeaders</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                           </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Set</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics">URI</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> exclude</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                           </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> retryTimes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> clientResponse</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 根据指定的重试次数进行重试</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> retryTimes</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">resend</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> duration</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> httpHeaders</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exclude</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">resend</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">R</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> response</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                           </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                           </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Duration</span><span class="token plain"> duration</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                           </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpHeaders</span><span class="token plain"> httpHeaders</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                           </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Set</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics">URI</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> exclude</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> response</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onErrorResume</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">th </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DIVIDE_SELECTOR_ID</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> loadBalance </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">LOAD_BALANCE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//查询可用服务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Upstream</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> upstreamList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">UpstreamCacheManager</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findUpstreamListBySelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> trimUri </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">trim</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">URI</span><span class="token plain"> needToExclude </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> exclude</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token comment" style="color:#999988;font-style:italic">// exclude already called</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">needToExclude</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHost</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">":"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> needToExclude</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPort</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">trimUri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstreamList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// no need to retry anymore</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CANNOT_FIND_HEALTHY_UPSTREAM_URL_AFTER_FAILOVER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMsg</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 请求ip</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ip </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">requireNonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRemoteAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHostAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 实现负载均衡</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Upstream</span><span class="token plain"> upstream </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">LoadBalancerFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstreamList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> loadBalance</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstream</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// no need to retry anymore</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CANNOT_FIND_HEALTHY_UPSTREAM_URL_AFTER_FAILOVER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMsg</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">URI</span><span class="token plain"> newUri </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RequestUrlUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildRequestUri</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> upstream</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildDomain</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 排除已经调用的uri</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            exclude</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">newUri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">             </span><span class="token comment" style="color:#999988;font-style:italic">// 进行再次调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMethodValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> newUri</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> httpHeaders</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBody</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">timeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">duration</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">TimeoutException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Response took longer than timeout: "</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> duration</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doOnError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.plugin.httpclient.WebClientPlugin#doRequest()</li>
</ul>
<p>在<code>doRequest()</code>方法中通过<code>webClient</code>发起真正的请求调用。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ClientResponse</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> httpMethod</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">URI</span><span class="token plain"> uri</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                             </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">HttpHeaders</span><span class="token plain"> httpHeaders</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Flux</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataBuffer</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> body</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> webClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">method</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpMethod</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">valueOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">httpMethod</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">uri</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//请求uri</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">headers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">headers </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> headers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">httpHeaders</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 请求header</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">body</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">BodyInserters</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromDataBuffers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">exchange</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 发起请求</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doOnSuccess</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">res </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">res</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">statusCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">is2xxSuccessful</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 成功</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CLIENT_RESPONSE_RESULT_TYPE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 失败</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CLIENT_RESPONSE_RESULT_TYPE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">ERROR</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setStatusCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">res</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">statusCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CLIENT_RESPONSE_ATTR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> res</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-处理响应结果">2.5 处理响应结果<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#25-%E5%A4%84%E7%90%86%E5%93%8D%E5%BA%94%E7%BB%93%E6%9E%9C" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">org.apache.shenyu.plugin.response.ResponsePlugin#execute()</li>
</ul>
<p>响应结果由<code>ResponsePlugin</code>插件处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuContext</span><span class="token plain"> shenyuContext </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CONTEXT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">assert</span><span class="token plain"> shenyuContext </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 根据rpc类型处理结果</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> writerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">writeWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>处理类型由<code>MessageWriter</code>决定，类继承关系如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/MessageWriter-81d10e88b3d5524b1eb2737c238956a6.png" width="1426" height="290" class="img_ev3q"></p>
<ul>
<li class="">MessageWriter：接口，定义消息处理方法；</li>
<li class="">NettyClientMessageWriter：处理<code>Netty</code>调用结果；</li>
<li class="">RPCMessageWriter：处理<code>RPC</code>调用结果；</li>
<li class="">WebClientMessageWriter：处理<code>WebClient</code>调用结果；</li>
</ul>
<p>默认是通过<code>WebCient</code>发起<code>http</code>请求。</p>
<ul>
<li class="">org.apache.shenyu.plugin.response.strategy.WebClientMessageWriter#writeWith()</li>
</ul>
<p>在<code>writeWith()</code>方法中处理响应结果。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">writeWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">defer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 获取响应</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ServerHttpResponse</span><span class="token plain"> response </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ClientResponse</span><span class="token plain"> clientResponse </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CLIENT_RESPONSE_ATTR</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clientResponse</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Object</span><span class="token plain"> error </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuResultWrap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SERVICE_RESULT_ERROR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">WebFluxResultUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">result</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//获取cookies和headers</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            response</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCookies</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">putAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clientResponse</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cookies</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            response</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">putAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clientResponse</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">headers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">asHttpHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// image, pdf or stream does not do format processing.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 处理特殊响应类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clientResponse</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">headers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">contentType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> media </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> clientResponse</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">headers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">contentType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toLowerCase</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">media</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">matches</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">COMMON_BIN_MEDIA_TYPE_REGEX</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> response</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">writeWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clientResponse</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">body</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">BodyExtractors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toDataBuffers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doOnCancel</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">clean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 处理一般响应类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            clientResponse </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ResponseUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildClientResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">response</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> clientResponse</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">body</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">BodyExtractors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toDataBuffers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> clientResponse</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">bodyToMono</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flatMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">originData </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">WebFluxResultUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">result</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> originData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doOnCancel</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">clean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>分析至此，关于<code>Divide</code>插件的源码分析就完成了，分析流程图如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/divide-execute-zh-c145705430fc3aec6e561cc4ad183a05.png" width="2065" height="644" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-小结">3. 小结<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Divide-Plugin#3-%E5%B0%8F%E7%BB%93" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>本文源码分析从<code>http</code>服务注册开始，到<code>divide</code>插件的服务调用。<code>divide</code>插件主要用来处理<code>http</code>请求。有些源码没有进入深入分析，比如负载均衡的实现，服务探活，将在后续继续分析。</p>]]></content>
        <author>
            <name>midnight2104</name>
            <uri>https://github.com/midnight2104</uri>
        </author>
        <category label="plugin" term="plugin"/>
        <category label="divide" term="divide"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Dubbo插件源码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin</id>
        <link href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[Apache ShenYu 是一个异步的，高性能的，跨语言的，响应式的 API 网关。]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p><a href="https://shenyu.apache.org/zh/docs/index" target="_blank" rel="noopener noreferrer" class="">Apache ShenYu</a> 是一个异步的，高性能的，跨语言的，响应式的 <code>API</code> 网关。</p>
</blockquote>
<p><code>Apache ShenYu</code> 网关使用 <code>dubbo</code> 插件完成对 <code>dubbo</code>服务的调用。你可以查看官方文档 <a href="https://shenyu.apache.org/docs/quick-start/quick-start-dubbo" target="_blank" rel="noopener noreferrer" class="">Dubbo快速开始</a> 了解如何使用该插件。</p>
<blockquote>
<p>本文基于<code>shenyu-2.4.3</code>版本进行源码分析，官网的介绍请参考 <a href="https://shenyu.apache.org/zh/docs/user-guide/dubbo-proxy/" target="_blank" rel="noopener noreferrer" class="">Dubbo服务接入</a> 。</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-服务注册">1. 服务注册<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#1-%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>以官网提供的例子为例 <a href="https://github.com/apache/incubator-shenyu/tree/master/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service" target="_blank" rel="noopener noreferrer" class="">shenyu-examples-dubbo</a> 。 假如你的<code>dubbo</code>服务定义如下(<code>spring-dubbo.xml</code>)：</p>
<div class="language-xml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-xml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">beans</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">xmlns</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">http://www.springframework.org/schema/beans</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">       </span><span class="token tag attr-name namespace" style="color:#00a4db;opacity:0.7">xmlns:</span><span class="token tag attr-name" style="color:#00a4db">xsi</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">http://www.w3.org/2001/XMLSchema-instance</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">       </span><span class="token tag attr-name namespace" style="color:#00a4db;opacity:0.7">xmlns:</span><span class="token tag attr-name" style="color:#00a4db">dubbo</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">http://code.alibabatech.com/schema/dubbo</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"></span><br></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f">       </span><span class="token tag attr-name namespace" style="color:#00a4db;opacity:0.7">xsi:</span><span class="token tag attr-name" style="color:#00a4db">schemaLocation</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">http://www.springframework.org/schema/beans</span><br></span><span class="token-line" style="color:#393A34"><span class="token tag attr-value" style="color:#e3116c">       http://www.springframework.org/schema/beans/spring-beans.xsd</span><br></span><span class="token-line" style="color:#393A34"><span class="token tag attr-value" style="color:#e3116c">       http://code.alibabatech.com/schema/dubbo</span><br></span><span class="token-line" style="color:#393A34"><span class="token tag attr-value" style="color:#e3116c">       https://code.alibabatech.com/schema/dubbo/dubbo.xsd</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag namespace" style="color:#00009f;opacity:0.7">dubbo:</span><span class="token tag" style="color:#00009f">application</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">name</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">test-dubbo-service</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag namespace" style="color:#00009f;opacity:0.7">dubbo:</span><span class="token tag" style="color:#00009f">registry</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">address</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">${dubbo.registry.address}</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag namespace" style="color:#00009f;opacity:0.7">dubbo:</span><span class="token tag" style="color:#00009f">protocol</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">name</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">dubbo</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">port</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">20888</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag namespace" style="color:#00009f;opacity:0.7">dubbo:</span><span class="token tag" style="color:#00009f">service</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">timeout</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">10000</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">interface</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">org.apache.shenyu.examples.dubbo.api.service.DubboTestService</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">ref</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">dubboTestService</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">beans</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<p>声明应用服务名称，注册中心地址，使用<code>dubbo</code>协议，声明服务接口，对应接口实现类：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * DubboTestServiceImpl.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Service</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"dubboTestService"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DubboTestServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">DubboTestService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ShenyuDubboClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/findById"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> desc </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Query by Id"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">DubboTest</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">findById</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DubboTest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hello world shenyu Apache, findById"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>在接口实现类中，使用注解<code>@ShenyuDubboClient</code>向<code>shenyu-admin</code>注册服务。该注解的作用及原理，稍后再进行分析。</p>
<p>在配置文件<code>application.yml</code>中的配置信息：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">server</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8011</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">address</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 0.0.0.0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">servlet</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">context-path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spring</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">main</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">allow-bean-definition-overriding</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">dubbo</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">registry</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">address</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> zookeeper</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//localhost</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">2181</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># dubbo使用的注册中心</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">register</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">registerType</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http </span><span class="token comment" style="color:#999988;font-style:italic">#注册方式</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">serverLists</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//localhost</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">9095</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">#注册地址</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">props</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">username</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> admin </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">password</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">123456</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">client</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">dubbo</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">props</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">contextPath</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /dubbo  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">appName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> dubbo</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>在配置文件中，声明<code>dubbo</code>使用的注册中心地址，<code>dubbo</code>服务向<code>shenyu-admin</code>注册，使用的方式是<code>http</code>，注册地址是<code>http://localhost:9095</code>。</p>
<p>关于注册方式的使用，请参考 <a href="https://shenyu.apache.org/docs/design/register-center-design/" target="_blank" rel="noopener noreferrer" class="">应用客户端接入</a> 。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="11--声明注册接口">1.1  声明注册接口<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#11--%E5%A3%B0%E6%98%8E%E6%B3%A8%E5%86%8C%E6%8E%A5%E5%8F%A3" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>使用注解<code>@ShenyuDubboClient</code>将服务注册到网关。简单<code>demo</code>如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// dubbo服务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Service</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"dubboTestService"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DubboTestServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">DubboTestService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ShenyuDubboClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/findById"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> desc </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Query by Id"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 需要注册的方法</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">DubboTest</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">findById</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DubboTest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hello world shenyu Apache, findById"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>注解定义：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 作用于类和方法上</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Retention</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RetentionPolicy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RUNTIME</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Target</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token class-name">ElementType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TYPE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ElementType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">METHOD</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Inherited</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@interface</span><span class="token plain"> </span><span class="token class-name">ShenyuDubboClient</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">//注册路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//规则名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ruleName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//描述信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">desc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//是否启用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">enabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="12-扫描注解信息">1.2 扫描注解信息<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#12-%E6%89%AB%E6%8F%8F%E6%B3%A8%E8%A7%A3%E4%BF%A1%E6%81%AF" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>注解扫描通过<code>ApacheDubboServiceBeanListener</code>完成，它实现了<code>ApplicationListener&lt;ContextRefreshedEvent&gt;</code>接口，在<code>Spring</code>容器启动过程中，发生上下文刷新事件时，开始执行事件处理方法<code>onApplicationEvent()</code>。</p>
<p>在构造器实例化的过程中：</p>
<ul>
<li class="">读取属性配置</li>
<li class="">开启线程池</li>
<li class="">启动注册中心，用于向<code>shenyu-admin</code>注册</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ApacheDubboServiceBeanListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ContextRefreshedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//构造器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ApacheDubboServiceBeanListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PropertiesConfig</span><span class="token plain"> clientConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token plain"> shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//1.读取属性配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Properties</span><span class="token plain"> props </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> clientConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> contextPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CONTEXT_PATH</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> appName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APP_NAME</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuClientIllegalArgumentException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"apache dubbo client must config the contextPath or appName"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">contextPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> contextPath</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">appName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> appName</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">host </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HOST</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">port </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PORT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//2.开启线程池</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        executorService </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Executors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newSingleThreadExecutor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ThreadFactoryBuilder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setNameFormat</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"shenyu-apache-dubbo-client-thread-pool-%d"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//3.启动注册中心</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 上下文刷新事件，执行方法逻辑</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ContextRefreshedEvent</span><span class="token plain"> contextRefreshedEvent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">ApacheDubboServiceBeanListener#onApplicationEvent()</li>
</ul>
<p>重写的方法逻辑：读取<code>Dubbo</code>服务<code>ServiceBean</code>，构建元数据对象和<code>URI</code>对象，并向<code>shenyu-admin</code>注册。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ContextRefreshedEvent</span><span class="token plain"> contextRefreshedEvent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//读取ServiceBean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">ServiceBean</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> serviceBean </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> contextRefreshedEvent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getApplicationContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBeansOfType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ServiceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//保证该方法只执行一次</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">registered</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">compareAndSet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//处理元数据对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Map</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">Entry</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">ServiceBean</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> entry </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">entrySet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">handler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">entry</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//处理URI对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">values</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findFirst</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bean </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildURIRegisterDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bean</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">
<p>handler()</p>
<p>在<code>handler()</code>方法中，从<code>serviceBean</code>中读取所有方法，判断方法上是否有<code>ShenyuDubboClient</code>注解，如果存在就构建元数据对象，并通过注册中心，向<code>shenyu-admin</code>注册该方法。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServiceBean</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//获取代理对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Object</span><span class="token plain"> refProxy </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRef</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//获取class信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> clazz </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> refProxy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getClass</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">AopUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isAopProxy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">refProxy</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            clazz </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">AopUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getTargetClass</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">refProxy</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//获取所有方法</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Method</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> methods </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ReflectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUniqueDeclaredMethods</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clazz</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Method</span><span class="token plain"> method </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> methods</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//读取ShenyuDubboClient注解信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ShenyuDubboClient</span><span class="token plain"> shenyuDubboClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuDubboClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuDubboClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">//构建元数据对象，并注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildMetaDataDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> shenyuDubboClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">
<p>buildMetaDataDTO()</p>
<p>构建元数据对象，在这里构建方法注册的必要信息，后续用于选择器或规则匹配。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildMetaDataDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServiceBean</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuDubboClient</span><span class="token plain"> shenyuDubboClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Method</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//应用名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> appName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildAppName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//方法路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> path </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> contextPath </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> shenyuDubboClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//描述信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> desc </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> shenyuDubboClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">desc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//服务名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> serviceName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInterface</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//规则名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> configRuleName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> shenyuDubboClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ruleName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> ruleName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">configRuleName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> path </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> configRuleName</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//方法名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> methodName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//参数类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> parameterTypesClazz </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getParameterTypes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> parameterTypes </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Arrays</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">parameterTypesClazz</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Class</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">joining</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">","</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">appName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">appName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">serviceName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">methodName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">methodName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">contextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">host</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildHost</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">port</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildPort</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ruleName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">pathDesc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">desc</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parameterTypes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">parameterTypes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcExt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildRpcExt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//dubbo服务的扩展信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DUBBO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">enabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuDubboClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">enabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">
<p>buildRpcExt()</p>
<p><code>dubbo</code>服务的扩展信息</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRpcExt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServiceBean</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       </span><span class="token class-name">DubboRpcExt</span><span class="token plain"> build </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DubboRpcExt</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">               </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">group</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">)</span><span class="token comment" style="color:#999988;font-style:italic">//分组</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">               </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">version</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getVersion</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getVersion</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">)</span><span class="token comment" style="color:#999988;font-style:italic">//版本</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">               </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">loadbalance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLoadbalance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLoadbalance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DEFAULT_LOADBALANCE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token comment" style="color:#999988;font-style:italic">//负载均衡策略，默认随机</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">               </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">retries</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRetries</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DEFAULT_RETRIES</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRetries</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token comment" style="color:#999988;font-style:italic">//重试次数，默认2</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">               </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">timeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DEFAULT_CONNECT_TIMEOUT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token comment" style="color:#999988;font-style:italic">//超时，默认3000</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">               </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DEFAULT_SENT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token comment" style="color:#999988;font-style:italic">//sent，默认false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">               </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cluster</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCluster</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCluster</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DEFAULT_CLUSTER</span><span class="token punctuation" style="color:#393A34">)</span><span class="token comment" style="color:#999988;font-style:italic">//集群策略，默认failover</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">               </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">url</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">               </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">build</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">
<p>buildURIRegisterDTO()</p>
<p>构建<code>URI</code>对象，注册服务本身的信息，后续可用于服务探活。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">URIRegisterDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildURIRegisterDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServiceBean</span><span class="token plain"> serviceBean</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">URIRegisterDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">contextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//上下文路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">appName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildAppName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token comment" style="color:#999988;font-style:italic">//应用名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DUBBO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token comment" style="color:#999988;font-style:italic">//rpc类型：dubbo</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">host</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildHost</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//host</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">port</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildPort</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serviceBean</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token comment" style="color:#999988;font-style:italic">//port</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>具体的注册逻辑由注册中心实现，请参考 <a href="https://shenyu.apache.org/zh/docs/design/register-center-design/" target="_blank" rel="noopener noreferrer" class="">客户端接入原理</a> 。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">//向注册中心，发布注册事件   </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="13-处理注册信息">1.3 处理注册信息<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#13-%E5%A4%84%E7%90%86%E6%B3%A8%E5%86%8C%E4%BF%A1%E6%81%AF" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>客户端通过注册中心注册的元数据和<code>URI</code>数据，在<code>shenyu-admin</code>端进行处理，负责存储到数据库和同步给<code>shenyu</code>网关。<code>Dubbo</code>插件的客户端注册处理逻辑在<code>ShenyuClientRegisterDubboServiceImpl</code>中。继承关系如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/ShenyuClientRegisterDubboServiceImpl-a48cc4b745cb6a47ee000cf08d4cff04.png" width="977" height="577" class="img_ev3q"></p>
<ul>
<li class="">ShenyuClientRegisterService：客户端注册服务，顶层接口；</li>
<li class="">FallbackShenyuClientRegisterService：注册失败，提供重试操作；</li>
<li class="">AbstractShenyuClientRegisterServiceImpl：抽象类，实现部分公共注册逻辑；</li>
<li class="">ShenyuClientRegisterDubboServiceImpl：实现<code>Dubbo</code>插件的注册；</li>
</ul>
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="131-注册服务">1.3.1 注册服务<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#131-%E6%B3%A8%E5%86%8C%E6%9C%8D%E5%8A%A1" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h5>
<ul>
<li class="">
<p>org.apache.shenyu.admin.service.register.AbstractShenyuClientRegisterServiceImpl#register()</p>
<p>客户端通过注册中心注册的元数据<code>MetaDataRegisterDTO</code>对象在<code>shenyu-admin</code>的<code>register()</code>方法被接送到。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">register</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//1. 注册选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> selectorHandler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">selectorHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> selectorId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginNameAdapter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcTypeAdapter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//2. 注册规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> ruleHandler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ruleHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RuleDTO</span><span class="token plain"> ruleDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRpcDefaultRuleDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ruleService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//3. 注册元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">registerMetadata</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//4. 注册ContextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> contextPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">registerContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h6 class="anchor anchorTargetStickyNavbar_Vzrq" id="1311-注册选择器">1.3.1.1 注册选择器<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#1311-%E6%B3%A8%E5%86%8C%E9%80%89%E6%8B%A9%E5%99%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h6>
<ul>
<li class="">org.apache.shenyu.admin.service.impl.SelectorServiceImpl#registerDefault()</li>
</ul>
<p>构建<code>contextPath</code>，查找选择器信息是否存在，如果存在就返回<code>id</code>；不存在就创建默认的选择器信息。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建contextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> contextPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ContextPathUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAppName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 通过名称查找选择器信息是否存在</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">findByNameAndPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 不存在就创建默认的选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">
<p>默认选择器信息</p>
<p>在这里构建默认选择器信息及其条件属性。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">//注册选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//构建选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildSelectorDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selectByName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//注册默认选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">//构建选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">SelectorDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildSelectorDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> pluginId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//构建默认选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildDefaultSelectorDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setPluginId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic">//构建默认选择器的条件属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setSelectorConditions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildDefaultSelectorConditionDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">构建默认选择器</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">SelectorDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildDefaultSelectorDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> name</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">SelectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">type</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CUSTOM_FLOW</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 默认类型自定义</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">matchMode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MatchModeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">AND</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//默认匹配方式 and</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">enabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">//默认启开启</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">loged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">//默认记录日志</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">continued</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//默认继续后续选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sort</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//默认顺序1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">构建默认选择器条件属性</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorConditionDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildDefaultSelectorConditionDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">SelectorConditionDTO</span><span class="token plain"> selectorConditionDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">SelectorConditionDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setParamType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ParamTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 默认参数类型URI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setParamName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setOperator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">OperatorEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">MATCH</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAlias</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 默认匹配策略 match</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setParamValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">AdminConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI_SUFFIX</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 默认值 /contextPath/**</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">注册默认选择器</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorDTO</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">SelectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//选择器条件属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorConditionDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectorConditionDTOs </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSelectorConditions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 向数据库插入选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic">// 向数据库插入选择器条件属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setSelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">            selectorConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">SelectorConditionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildSelectorConditionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 发布同步事件，向网关同步选择信息及其条件属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorConditionDTOs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h6 class="anchor anchorTargetStickyNavbar_Vzrq" id="1312-注册规则">1.3.1.2 注册规则<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#1312-%E6%B3%A8%E5%86%8C%E8%A7%84%E5%88%99" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h6>
<p>在注册服务的第二步中，开始构建默认规则，然后注册规则。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">register</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//1. 注册选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//2. 注册规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 默认规则处理属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> ruleHandler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ruleHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建默认规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RuleDTO</span><span class="token plain"> ruleDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRpcDefaultRuleDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 注册规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ruleService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//3. 注册元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//4. 注册ContextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">默认规则处理属性</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ruleHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 默认规则处理属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DubboRuleHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>Dubbo</code>插件默认规则处理属性</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DubboRuleHandle</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">RuleHandle</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * dubbo服务版本信息.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> version</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 分组.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> group</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 重试次数.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Integer</span><span class="token plain"> retries </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 负载均衡策略：默认随机</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> loadbalance </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">LoadBalanceEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RANDOM</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 超时，默认3000</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> timeout </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TIME_OUT</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">构建默认规则信息</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 构建默认规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">RuleDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRpcDefaultRuleDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> metaDataDTO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ruleHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRuleDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleHandler</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaDataDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRuleName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaDataDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">//  构建默认规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">RuleDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRuleDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ruleHandler</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ruleName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RuleDTO</span><span class="token plain"> ruleDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RuleDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//关联的选择器id</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//规则名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">matchMode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MatchModeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">AND</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 默认匹配模式 and</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">enabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 默认开启</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">loged</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//默认记录日志</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sort</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//默认顺序 1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RuleConditionDTO</span><span class="token plain"> ruleConditionDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RuleConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">paramType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ParamTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 默认参数类型URI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">paramName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">paramValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//参数值path</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">indexOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"*"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            ruleConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setOperator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">OperatorEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">MATCH</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAlias</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//如果path中有*，操作类型则默认为 match</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            ruleConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setOperator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">OperatorEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">EQ</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAlias</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 否则，默认操作类型 = </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ruleDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setRuleConditions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> ruleDTO</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.admin.service.impl.RuleServiceImpl#registerDefault()</li>
</ul>
<p>注册规则：向数据库插入记录，并向网关发布事件，进行数据同步。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RuleDTO</span><span class="token plain"> ruleDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RuleDO</span><span class="token plain"> exist </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ruleMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findBySelectorIdAndName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exist</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RuleDO</span><span class="token plain"> ruleDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RuleDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildRuleDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleConditionDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> ruleConditions </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ruleDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRuleConditions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 向数据库插入规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            ruleMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//向数据库插入规则体条件属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            ruleConditions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleConditionDTO </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                ruleConditionDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setRuleId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">                ruleConditionMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insertSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RuleConditionDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildRuleConditionDO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleConditionDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 向网关发布事件，进行数据同步</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleConditions</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> ruleDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<h6 class="anchor anchorTargetStickyNavbar_Vzrq" id="1313-注册元数据">1.3.1.3 注册元数据<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#1313-%E6%B3%A8%E5%86%8C%E5%85%83%E6%95%B0%E6%8D%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h6>
<p>元数据主要用于<code>RPC</code>服务的调用。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">register</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//1. 注册选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//2. 注册规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//3. 注册元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">registerMetadata</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//4. 注册ContextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">
<p>org.apache.shenyu.admin.service.register.ShenyuClientRegisterDubboServiceImpl#registerMetadata()</p>
<p>插入或更新元数据，然后发布同步事件到网关。</p>
</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerMetadata</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 获取metaDataService</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">MetaDataService</span><span class="token plain"> metaDataService </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getMetaDataService</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据是否存在</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">MetaDataDO</span><span class="token plain"> exist </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> metaDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findByPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 插入或更新元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">saveOrUpdateMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exist</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">saveOrUpdateMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataDO</span><span class="token plain"> exist</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> metaDataDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">DataEventTypeEnum</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 数据类型转换 DTO-&gt;DO</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">MetaDataDO</span><span class="token plain"> metaDataDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">MetaDataTransfer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">mapRegisterDTOToEntity</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 插入数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exist</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Timestamp</span><span class="token plain"> currentTime </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Timestamp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">System</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">currentTimeMillis</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">UUIDUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">generateShortUuid</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setDateCreated</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">currentTime</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setDateUpdated</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">currentTime</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insert</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            eventType </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CREATE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 更新数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exist</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            metaDataMapper</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">update</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            eventType </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 发布同步事件到网关</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> eventType</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MetaDataTransfer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">mapToData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="132-注册uri">1.3.2 注册URI<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#132-%E6%B3%A8%E5%86%8Curi" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h5>
<ul>
<li class="">org.apache.shenyu.admin.service.register.FallbackShenyuClientRegisterService#registerURI()</li>
</ul>
<p>服务端收到客户端注册的<code>URI</code>信息后，进行处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">key</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeFallBack</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 注册URI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doRegisterURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            logger</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Register success: {},{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Exception</span><span class="token plain"> ex</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            logger</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">warn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Register exception: cause:{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ex</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 注册失败后，进行重试</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addFallback</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">FallbackHolder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.admin.service.register.AbstractShenyuClientRegisterServiceImpl#doRegisterURI()</li>
</ul>
<p>从客户端注册的<code>URI</code>中获取有效的<code>URI</code>，更新对应的选择器<code>handle</code>属性，向网关发送选择器更新事件。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doRegisterURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//参数检查</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//获取选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findByNameAndPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginNameAdapter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcTypeAdapter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"doRegister Failed to execute,wait to retry."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取有效的URI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> validUriList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPort</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHost</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建选择器的handle属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> handler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">validUriList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildByName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginNameAdapter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcTypeAdapter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 向数据库更新选择器的handle属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 向网关发送选择器更新事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>关于服务注册的源码分析就以及完成了，分析流程图如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/dubbo-register-zh-3a94f676f21cccb70d92c1e9e1eaad29.png" width="1956" height="699" class="img_ev3q"></p>
<p>接下来就分析<code>dubbo</code>插件是如何根据这些信息向<code>http</code>服务发起调用。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-服务调用">2. 服务调用<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#2-%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p><code>dubbo</code>插件是<code>ShenYu</code>网关用于将<code>http</code>请求转成 <code>dubbo协议</code>，调用<code>dubbo</code>服务的核心处理插件。</p>
<p>以官网提供的案例 <a href="https://shenyu.apache.org/docs/quick-start/quick-start-dubbo/" target="_blank" rel="noopener noreferrer" class="">Dubbo快速开始</a> 为例，一个<code>dubbo</code>服务通过注册中心向<code>shenyu-admin</code>注册后，通过<code>ShenYu</code>网关代理，请求如下：</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">GET http://localhost:9195/dubbo/findById?id=100</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Accept: application/json</span><br></span></code></pre></div></div>
<p><code>Dubbo</code>插件中，类继承关系如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/ApacheDubboPlugin-286a36694f3fa121e7d3c7d67d08b833.png" width="491" height="627" class="img_ev3q"></p>
<ul>
<li class="">ShenyuPlugin：顶层接口，定义接口方法；</li>
<li class="">AbstractShenyuPlugin：抽象类，实现插件共有逻辑；</li>
<li class="">AbstractDubboPlugin：dubbo插件抽象类，实现<code>dubbo</code>共有逻辑；</li>
<li class="">ApacheDubboPlugin：ApacheDubbo插件。</li>
</ul>
<blockquote>
<p>ShenYu网关支持ApacheDubbo和AlibabaDubbo</p>
</blockquote>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="21-接收请求">2.1 接收请求<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#21-%E6%8E%A5%E6%94%B6%E8%AF%B7%E6%B1%82" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>通过<code>ShenYu</code>网关代理后，请求入口是<code>ShenyuWebHandler</code>，它实现了<code>org.springframework.web.server.WebHandler</code>接口。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuWebHandler</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">WebHandler</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SortPluginEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 处理web请求</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       </span><span class="token comment" style="color:#999988;font-style:italic">// 执行默认插件链</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> execute </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DefaultShenyuPluginChain</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">plugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">scheduled</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> execute</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">subscribeOn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">scheduler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> execute</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DefaultShenyuPluginChain</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> index</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ShenyuPlugin</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> plugins</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * 实例化默认插件链</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">DefaultShenyuPluginChain</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ShenyuPlugin</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> plugins</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">plugins </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> plugins</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * 执行每个插件.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">defer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">index </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> plugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 获取当前执行插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">ShenyuPlugin</span><span class="token plain"> plugin </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> plugins</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">index</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 是否跳过当前插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> skip </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> plugin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">skip</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">skip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果跳过就执行下一个</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 执行当前插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> plugin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">empty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="22-匹配规则">2.2 匹配规则<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#22-%E5%8C%B9%E9%85%8D%E8%A7%84%E5%88%99" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">org.apache.shenyu.plugin.base.AbstractShenyuPlugin#execute()</li>
</ul>
<p>在<code>execute()</code>方法中执行选择器和规则的匹配逻辑。</p>
<ul>
<li class="">匹配选择器；</li>
<li class="">匹配规则；</li>
<li class="">执行插件。</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 插件名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> pluginName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">named</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 插件信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">PluginData</span><span class="token plain"> pluginData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">obtainPluginData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> pluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEnabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">SelectorData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> selectors </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">obtainSelectorData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectors</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleSelectorIfNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 匹配选择器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">matchSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectors</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleSelectorIfNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">selectorLog</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RuleData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> rules </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">BaseDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">obtainRuleData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rules</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleRuleIfNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 匹配规则</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">RuleData</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">SelectorTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">FULL_FLOW</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">//get last</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                rule </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> rules</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rules</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                rule </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">matchRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> rules</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleRuleIfNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">ruleLog</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rule</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pluginName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 执行插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doExecute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="23-执行globalplugin">2.3 执行GlobalPlugin<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#23-%E6%89%A7%E8%A1%8Cglobalplugin" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">org.apache.shenyu.plugin.global.GlobalPlugin#execute()</li>
</ul>
<p><code>GlobalPlugin</code>是一个全局插件，在<code>execute()</code>方法中构建上下文信息。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">GlobalPlugin</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ShenyuPlugin</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 构建上下文信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuContextBuilder</span><span class="token plain"> builder</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       </span><span class="token comment" style="color:#999988;font-style:italic">// 构建上下文信息，传入到 exchange 中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuContext</span><span class="token plain"> shenyuContext </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> builder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CONTEXT</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> shenyuContext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.plugin.global.DefaultShenyuContextBuilder#build()</li>
</ul>
<p>构建默认的上下文信息。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DefaultShenyuContextBuilder</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ShenyuContextBuilder</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuContext</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//构建参数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Pair</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">MetaData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> buildData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//包装ShenyuContext</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> decoratorMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">buildData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLeft</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">decorator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildDefaultContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> buildData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRight</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Pair</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">MetaData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//根据请求的uri获取元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">MetaData</span><span class="token plain"> metaData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">MetaDataCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">obtain</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEnabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Pair</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">of</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Pair</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">of</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">MetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//设置默认的上下文信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">ShenyuContext</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildDefaultContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerHttpRequest</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> appKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getFirst</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APP_KEY</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> sign </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getFirst</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SIGN</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> timestamp </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getFirst</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TIMESTAMP</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuContext</span><span class="token plain"> shenyuContext </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> path </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        shenyuContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//请求路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        shenyuContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setAppKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">appKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        shenyuContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setSign</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sign</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        shenyuContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setTimestamp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        shenyuContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setStartDateTime</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">LocalDateTime</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">now</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMethod</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">httpMethod </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> shenyuContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setHttpMethod</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">httpMethod</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//请求方法</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> shenyuContext</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.plugin.dubbo.common.context.DubboShenyuContextDecorator#decorator()</li>
</ul>
<p>包装<code>ShenyuContext</code>：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">DubboShenyuContextDecorator</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ShenyuContextDecorator</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuContext</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">decorator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuContext</span><span class="token plain"> shenyuContext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaData</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        shenyuContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setModule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAppName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//获取AppName</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        shenyuContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setMethod</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getServiceName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//获取ServiceName</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        shenyuContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//获取contextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        shenyuContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setRpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DUBBO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// dubbo服务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> shenyuContext</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DUBBO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="24-执行rpcparamtransformplugin">2.4 执行RpcParamTransformPlugin<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#24-%E6%89%A7%E8%A1%8Crpcparamtransformplugin" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p><code>RpcParamTransformPlugin</code>负责从<code>http</code>请求中读取参数，保存到<code>exchange</code>中，传递给<code>rpc</code>服务。</p>
<ul>
<li class="">org.apache.shenyu.plugin.base.RpcParamTransformPlugin#execute()</li>
</ul>
<p>在<code>execute()</code>方法中，执行该插件的核心逻辑：从<code>exchange</code>中获取请求信息，根据请求传入的内容形式处理参数。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">RpcParamTransformPlugin</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ShenyuPlugin</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//从exchange中获取请求信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ServerHttpRequest</span><span class="token plain"> request </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuContext</span><span class="token plain"> shenyuContext </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CONTEXT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuContext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">           </span><span class="token comment" style="color:#999988;font-style:italic">// 如果请求参数格式是APPLICATION_JSON</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">MediaType</span><span class="token plain"> mediaType </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContentType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MediaType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APPLICATION_JSON</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isCompatibleWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">mediaType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">body</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 如果请求参数格式是APPLICATION_FORM_URLENCODED</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MediaType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APPLICATION_FORM_URLENCODED</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isCompatibleWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">mediaType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">formData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//一般查询请求</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">query</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 如果请求参数格式是APPLICATION_JSON</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">body</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerHttpRequest</span><span class="token plain"> serverHttpRequest</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">from</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataBufferUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">join</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serverHttpRequest</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBody</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flatMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PARAM_TRANSFORM</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">resolveBodyFromRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//解析body，保存到exchange中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 如果请求参数格式是APPLICATION_FORM_URLENCODED</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">formData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerHttpRequest</span><span class="token plain"> serverHttpRequest</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">from</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataBufferUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">join</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serverHttpRequest</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBody</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flatMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">map </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">String</span><span class="token plain"> param </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">resolveBodyFromRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">map</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">LinkedMultiValueMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> linkedMultiValueMap</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        linkedMultiValueMap </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">BodyParamUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildBodyParams</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">URLDecoder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">decode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">param</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//格式化数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">UnsupportedEncodingException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PARAM_TRANSFORM</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">HttpParamConverter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> linkedMultiValueMap</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">// 保存到exchange中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//一般查询请求</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">query</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerHttpRequest</span><span class="token plain"> serverHttpRequest</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PARAM_TRANSFORM</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">HttpParamConverter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> serverHttpRequest</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getQuery</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//保存到exchange中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="25-执行dubboplugin">2.5 执行DubboPlugin<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#25-%E6%89%A7%E8%A1%8Cdubboplugin" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">org.apache.shenyu.plugin.dubbo.common.AbstractDubboPlugin#doExecute()</li>
</ul>
<p>在<code>doExecute()</code>方法中，主要是检查元数据和参数。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractDubboPlugin</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractShenyuPlugin</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doExecute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                   </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                   </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                   </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//获取参数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> param </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PARAM_TRANSFORM</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//获取上下文信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuContext</span><span class="token plain"> shenyuContext </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CONTEXT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">assert</span><span class="token plain"> shenyuContext </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//获取元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">MetaData</span><span class="token plain"> metaData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//检查元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token function" style="color:#d73a49">checkMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">" path is : {}, meta data have error : {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> shenyuContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setStatusCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INTERNAL_SERVER_ERROR</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Object</span><span class="token plain"> error </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuResultWrap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA_ERROR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">WebFluxResultUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">result</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//检查元数据和参数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNoneBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getParameterTypes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">param</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setStatusCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INTERNAL_SERVER_ERROR</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Object</span><span class="token plain"> error </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuResultWrap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DUBBO_HAVE_BODY_PARAM</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">WebFluxResultUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">result</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//设置rpcContext</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//进行dubbo服务调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doDubboInvoker</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> param</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.plugin.apache.dubbo.ApacheDubboPlugin#doDubboInvoker()</li>
</ul>
<p>在<code>doDubboInvoker()</code>方法中设置特殊的上下文信息，然后开始dubbo的泛化调用。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ApacheDubboPlugin</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractDubboPlugin</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doDubboInvoker</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaData</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> param</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//设置当前的选择器和规则信息，以及请求地址，用于支持dubbo的灰度</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RpcContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setAttachment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DUBBO_SELECTOR_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RpcContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setAttachment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DUBBO_RULE_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RpcContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setAttachment</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DUBBO_REMOTE_ADDRESS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">requireNonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRemoteAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHostAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//dubbo的泛化调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Object</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> dubboProxyService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">genericInvoker</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">param</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//执行下一个插件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.plugin.apache.dubbo.proxy.ApacheDubboProxyService#genericInvoker()</li>
</ul>
<p><code>genericInvoker()</code>方法：</p>
<ul>
<li class="">获取<code>ReferenceConfig</code>对象；</li>
<li class="">获取泛化服务<code>GenericService</code>对象；</li>
<li class="">构造请求参数<code>pair</code>对象；</li>
<li class="">发起异步的泛化调用。</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ApacheDubboProxyService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//...... </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Generic invoker object.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Object</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">genericInvoker</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> body</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaData</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//1.获取ReferenceConfig对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ReferenceConfig</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">GenericService</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> reference </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ApacheDubboConfigCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//如果没有获取到</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">reference</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInterface</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//失效当前缓存的信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ApacheDubboConfigCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">invalidate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//使用元数据进行再次初始化</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            reference </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ApacheDubboConfigCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">initRef</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//2.获取泛化服务GenericService对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">GenericService</span><span class="token plain"> genericService </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//3.构造请求参数pair对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Pair</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> pair</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getParameterTypes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token class-name">ParamCheckUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">dubboBodyIsEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            pair </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ImmutablePair</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            pair </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> dubboParamResolveService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildParameter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getParameterTypes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//4.发起异步的泛化调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromFuture</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">invokeAsync</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">genericService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMethodName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pair</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLeft</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pair</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRight</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">thenApply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ret </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//处理结果</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ret</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                ret </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DUBBO_RPC_RESULT_EMPTY</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RPC_RESULT</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ret</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttributes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CLIENT_RESPONSE_RESULT_TYPE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> ret</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onErrorMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exception </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> exception </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">GenericException</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">GenericException</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> exception</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getExceptionMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exception</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//处理异常</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//泛化调用，异步操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">CompletableFuture</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Object</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">invokeAsync</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">GenericService</span><span class="token plain"> genericService</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> parameterTypes</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> args</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">GenericException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        genericService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">$</span><span class="token function" style="color:#d73a49">invoke</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> parameterTypes</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> args</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Object</span><span class="token plain"> resultFromFuture </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RpcContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getFuture</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> resultFromFuture </span><span class="token keyword" style="color:#00009f">instanceof</span><span class="token plain"> </span><span class="token class-name">CompletableFuture</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CompletableFuture</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Object</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> resultFromFuture </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">CompletableFuture</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">completedFuture</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">resultFromFuture</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>通过泛化调用就可以实现在网关调用<code>dubbo</code>服务了。</p>
<p><code>ReferenceConfig</code>对象是支持泛化调用的关键对象 ，它的初始化操作是在数据同步的时候完成的。这里涉及两部分数据，一是同步的插件<code>handler</code>信息，二是同步的插件元数据信息。</p>
<ul>
<li class="">org.apache.shenyu.plugin.dubbo.common.handler.AbstractDubboPluginDataHandler#handlerPlugin()</li>
</ul>
<p>当插件数据更新时，数据同步模块会将数据从<code>shenyu-admin</code>同步到网关。在<code>handlerPlugin()</code>中执行初始化操作。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractDubboPluginDataHandler</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">PluginDataHandler</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//初始化配置缓存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">initConfigCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DubboRegisterConfig</span><span class="token plain"> dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handlerPlugin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PluginData</span><span class="token plain"> pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEnabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//数据反序列化</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">DubboRegisterConfig</span><span class="token plain"> dubboRegisterConfig </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pluginData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">DubboRegisterConfig</span><span class="token plain"> exist </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Singleton</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INST</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exist</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exist</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 执行初始化操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">initConfigCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Singleton</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INST</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">single</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.plugin.apache.dubbo.handler.ApacheDubboPluginDataHandler#initConfigCache()</li>
</ul>
<p>执行初始化操作。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ApacheDubboPluginDataHandler</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractDubboPluginDataHandler</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">initConfigCache</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DubboRegisterConfig</span><span class="token plain"> dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//执行初始化操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ApacheDubboConfigCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//失效之前缓存的结果</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ApacheDubboConfigCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">invalidateAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.plugin.apache.dubbo.cache.ApacheDubboConfigCache#init()</li>
</ul>
<p>在初始化中，设置<code>registryConfig</code>和<code>consumerConfig</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ApacheDubboConfigCache</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">DubboConfigCache</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......  </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 初始化</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DubboRegisterConfig</span><span class="token plain"> dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//创建ApplicationConfig</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">applicationConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            applicationConfig </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ApplicationConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"shenyu_proxy"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//协议或者地址发生改变时，需要更新registryConfig</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">needUpdateRegistryConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">RegistryConfig</span><span class="token plain"> registryConfigTemp </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">RegistryConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            registryConfigTemp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setProtocol</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProtocol</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            registryConfigTemp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"shenyu_proxy"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            registryConfigTemp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setRegister</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            registryConfigTemp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRegister</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">            </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">registryConfigTemp</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">setGroup</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            registryConfig </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> registryConfigTemp</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//创建ConsumerConfig</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">consumerConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            consumerConfig </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ApplicationModel</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getConfigManager</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getDefaultConsumer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">orElseGet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">ConsumerConfig</span><span class="token plain"> consumerConfig </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ConsumerConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                consumerConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">refresh</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> consumerConfig</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">           </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//设置ConsumerConfig</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getThreadpool</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">consumerConfig</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">setThreadpool</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCorethreads</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">consumerConfig</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">setCorethreads</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getThreads</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">consumerConfig</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">setThreads</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getQueues</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">consumerConfig</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">setQueues</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//是否需要更新注册配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">needUpdateRegistryConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DubboRegisterConfig</span><span class="token plain"> dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">registryConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProtocol</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> registryConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProtocol</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRegister</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> registryConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboRegisterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProtocol</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> registryConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProtocol</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.plugin.apache.dubbo.subscriber.ApacheDubboMetaDataSubscriber#onSubscribe()</li>
</ul>
<p>当元数据更新时，数据同步模块会将数据从<code>shenyu-admin</code>同步到网关。在<code>onSubscribe()</code>方法中执行元数据更新操作。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ApacheDubboMetaDataSubscriber</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">MetaDataSubscriber</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//本地内存缓存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConcurrentMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">MetaData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Maps</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newConcurrentMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//元数据发生更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onSubscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaData</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// dubbo服务的元数据更新</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DUBBO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//对应的元数据是否存在</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">MetaData</span><span class="token plain"> exist </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exist</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ApacheDubboConfigCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 首次初始化</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">ApacheDubboConfigCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">initRef</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 对应的元数据发生了更新操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getServiceName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exist</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getServiceName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRpcExt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exist</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRpcExt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getParameterTypes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exist</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getParameterTypes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMethodName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exist</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMethodName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">//根据最新的元数据再次构建ReferenceConfig</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">ApacheDubboConfigCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//本地内存缓存</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//删除元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">unSubscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaData</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DUBBO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//使ReferenceConfig失效</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ApacheDubboConfigCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">invalidate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">remove</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">org.apache.shenyu.plugin.apache.dubbo.cache.ApacheDubboConfigCache#initRef()</li>
</ul>
<p>通过<code>metaData</code>构建<code>ReferenceConfig</code>对象。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ApacheDubboConfigCache</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">DubboConfigCache</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ReferenceConfig</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">GenericService</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">initRef</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaData</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">//先尝试从缓存中获取，存在就直接返回</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">ReferenceConfig</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">GenericService</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> referenceConfig </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> cache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNoneBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">referenceConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInterface</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> referenceConfig</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ExecutionException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"init dubbo ref exception"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">           </span><span class="token comment" style="color:#999988;font-style:italic">//不存在，就构建</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Build reference config.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"deprecation"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ReferenceConfig</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">GenericService</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaData</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">applicationConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">registryConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ReferenceConfig</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ReferenceConfig</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">GenericService</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> reference </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ReferenceConfig</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//新建ReferenceConfig</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setGeneric</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"true"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//泛化调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setAsync</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//支持异步</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setApplication</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">applicationConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//设置应用配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setRegistry</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">registryConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//设置注册中心配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setConsumer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">consumerConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//设置消费者配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setInterface</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getServiceName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//设置服务接口</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setProtocol</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"dubbo"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//设置dubbo协议</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setCheck</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//不检查 service provider</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setLoadbalance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"gray"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//支持灰度</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> parameters </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">HashMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            parameters</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"dispatcher"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"direct"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setParameters</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">parameters</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//自定义参数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">String</span><span class="token plain"> rpcExt </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRpcExt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//rpc扩展参数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">DubboParam</span><span class="token plain"> dubboParam </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">parserToDubboParam</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rpcExt</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//反序列化</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboParam</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNoneBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboParam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getVersion</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setVersion</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboParam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getVersion</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//设置版本</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNoneBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboParam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setGroup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboParam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getGroup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//设置分组</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNoneBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboParam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboParam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//设置url</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNoneBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboParam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCluster</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setCluster</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboParam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCluster</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//设置Cluster type</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboParam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getTimeout</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">reference</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">setTimeout</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//timeout</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboParam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRetries</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">reference</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">setRetries</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//retires</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dubboParam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">reference</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">setSent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//Whether to ack async-sent</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">//获取GenericService</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Object</span><span class="token plain"> obj </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> reference</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">obj</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"init apache dubbo reference success there meteData is :{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> metaData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">//缓存当前的reference</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    cache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> reference</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Exception</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"init apache dubbo reference exception"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> reference</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="26-执行responseplugin">2.6 执行ResponsePlugin<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#26-%E6%89%A7%E8%A1%8Cresponseplugin" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class="">org.apache.shenyu.plugin.response.ResponsePlugin#execute()</li>
</ul>
<p>响应结果由<code>ResponsePlugin</code>插件处理。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuContext</span><span class="token plain"> shenyuContext </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CONTEXT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">assert</span><span class="token plain"> shenyuContext </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 根据rpc类型处理结果</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> writerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">writeWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>处理类型由<code>MessageWriter</code>决定，类继承关系如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/MessageWriter-81d10e88b3d5524b1eb2737c238956a6.png" width="1426" height="290" class="img_ev3q"></p>
<ul>
<li class="">MessageWriter：接口，定义消息处理方法；</li>
<li class="">NettyClientMessageWriter：处理<code>Netty</code>调用结果；</li>
<li class="">RPCMessageWriter：处理<code>RPC</code>调用结果；</li>
<li class="">WebClientMessageWriter：处理<code>WebClient</code>调用结果；</li>
</ul>
<p><code>Dubbo</code>服务调用，处理结果当然是<code>RPCMessageWriter</code>了。</p>
<ul>
<li class="">org.apache.shenyu.plugin.response.strategy.RPCMessageWriter#writeWith()</li>
</ul>
<p>在<code>writeWith()</code>方法中处理响应结果。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">RPCMessageWriter</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">MessageWriter</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">writeWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">defer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Object</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RPC_RESULT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//获取结果</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//处理异常</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Object</span><span class="token plain"> error </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuResultWrap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SERVICE_RESULT_ERROR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">WebFluxResultUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">result</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">WebFluxResultUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">result</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token comment" style="color:#999988;font-style:italic">//返回结果</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>分析至此，关于<code>Dubbo</code>插件的源码分析就完成了，分析流程图如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/dubbo-execute-zh-cd073b32b44fa14c94a575450d8b320d.png" width="2521" height="617" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-小结">3. 小结<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Dubbo-Plugin#3-%E5%B0%8F%E7%BB%93" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>本文源码分析从<code>Dubbo</code>服务注册开始，到<code>Dubbo</code>插件的服务调用。<code>Dubbo</code>插件主要用来处理将<code>http</code>请求转成<code>dubbo</code>协议,主要逻辑是通过泛化调用实现。</p>]]></content>
        <author>
            <name>midnight2104</name>
            <uri>https://github.com/midnight2104</uri>
        </author>
        <category label="plugin" term="plugin"/>
        <category label="dubbo" term="dubbo"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[McpServer 插件源码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Mcp-Server-Plugin</id>
        <link href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Mcp-Server-Plugin"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[在 shenyu 网关中，启动该插件，shenyu 将成为一个功能丰富的 mcpServer,]]></summary>
        <content type="html"><![CDATA[<p>在 shenyu 网关中，启动该插件，shenyu 将成为一个功能丰富的 mcpServer,
你可以通过简单配置来将一个服务作为 tool 注册到 shenyu 网关中，并使用网关提供的扩展功能。</p>
<blockquote>
<p>本文基于<code>shenyu-2.7.0.2</code>版本进行源码分析， 在本篇中我将追踪 Shenyu Mcp 插件链路，对 Mcp 插件的 sse 通信方式进行源码分析</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="前言">前言<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Mcp-Server-Plugin#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<blockquote>
<p>shenyu 网关的 mcp 插件基于 spring-ai-mcp 扩展而来，为了更好的了解 mcp 插件的工作原理
，我将简单介绍 mcp 官方提供的 jdk 中各个 java 类是如何协同运作的</p>
</blockquote>
<p>我想先简单介绍三个 Mcp 官方提供的 java 类</p>
<blockquote>
<ol>
<li class=""><code>McpServer</code></li>
</ol>
<p>该类负责管理，tool，Resource，promote 等资源</p>
<ol start="2">
<li class=""><code>TransportProvider</code></li>
</ol>
<p>根据客户端和服务端之间通信协议，提供之相对应的通讯方法</p>
<ol start="3">
<li class=""><code>Session</code></li>
</ol>
<p>处理请求数据、响应数据和通知数据，提供一些基本方法和其对应的处理器，查询工具，调用工具都在此处执行</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-服务注册">1. 服务注册<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Mcp-Server-Plugin#1-%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>在 shenyu admin 的 McpServer 中插件填写 endpoint 和 tool 信息后，这些信息将自动注册到 shenyu bootstrap 中，
数据同步源码可以参考官网<a href="https://shenyu.incubator.apache.org/zh/blog/DataSync-SourceCode-Analysis-WebSocket-Data-Sync" target="_blank" rel="noopener noreferrer" class="">websocket数据同步</a></p>
<p>shenyu bootstrap 将在 <code>McpServerPluginDataHandler</code> 的 <code>handler()</code> 方法中接收到 admin 同步来的数据。</p>
<p><code>handlerSelector()</code> 方法接收 url 数据创建 McpServer</p>
<p><code>handlerRule()</code> 方法接收 tool 信息，注册 tool</p>
<p>这两个方法共同组成了 Shenyu Mcp 插件的服务注册部分，下面我将对这个两个方法，详细展开分析</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="11-transportmcpserver注册">1.1 Transport，McpServer注册<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Mcp-Server-Plugin#11-transportmcpserver%E6%B3%A8%E5%86%8C" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>我们先来分析 <code>handlerSelector()</code> 方法，也就是 McpServer 的注册</p>
<ul>
<li class=""><code>handlerSelector()</code> 方法 工作内容如下</li>
</ul>
<ol>
<li class="">捕捉用户在 Selector 上的填写的 url，这个 url 将作为一个 key 存储 McpServer TransportProvider 等信息</li>
<li class="">序列化创建 <code>ShenyuMcpServer</code>，<code>ShenyuMcpServer</code> 将 SelectorId 和这些 url 也就是这些 key 绑定，以此来实现 selectorId 和 key 的绑定。</li>
</ol>
<blockquote>
<p>注意 <code>ShenyuMcpServer</code> 是 Shenyu 用于绑定 SelectorId 和 url 的对象，和 <code>McpServer</code> 没有继承关系，功能也完全不同</p>
</blockquote>
<ol start="3">
<li class="">调用 <code>ShenyuMcpServerManager</code> 的 <code>getOrCreateMcpServerTransport()</code> 方法注册 McpServer TransportProvider</li>
</ol>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">McpServerPluginDataHandler</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">PluginDataHandler</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handlerSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取URI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> uri </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getConditionList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">condition </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">condition</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getParamType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConditionData</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">getParamValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findFirst</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">orElse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建McpServer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuMcpServer</span><span class="token plain"> shenyuMcpServer </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">DEFAULT_MESSAGE_ENDPOINT</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuMcpServer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        shenyuMcpServer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 缓存shenyuMcpServer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">CACHED_SERVER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cachedHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                shenyuMcpServer</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> messageEndpoint </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> shenyuMcpServer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessageEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 尝试获取或者注册transportProvider</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        shenyuMcpServerManager</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getOrCreateMcpServerTransport</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uri</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> messageEndpoint</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<blockquote>
<p><code>ShenyuMcpServerManager</code> 该类是 ShenYu 中 McpServer 的管理中心，不仅储存了 <code>McpAsyncServer</code> <code>CompositeTransportProvider</code> 等内容，注册 Transport 和 McpServer
的方法也在其中</p>
</blockquote>
<ul>
<li class=""><code>getOrCreateMcpServerTransport()</code> 方法工作内容具体如下</li>
</ul>
<ol>
<li class="">处理传递来的 url 去除/streamablehttp 以及 /message后缀 使其恢复为原始的 url</li>
<li class="">尝试获取 <code>CompositeTransportProvider</code> 对象，该对象是 Transport 的复合对象，包含了多种协议对应的 Transport</li>
<li class="">如果没有获取到，则调用 <code>createSseTransport()</code> 方法创建 <code>CompositeTransportProvider</code> 对象</li>
<li class="">创建 <code>McpAsyncServer</code> 对象，保存 Transport 对象到 Map 中，将 Transport 注册到 <code>McpAsyncServer</code> 中</li>
</ol>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuMcpServerManager</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuSseServerTransportProvider</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getOrCreateMcpServerTransport</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> uri</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> messageEndPoint</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 去除/streamablehttp 以及 /message后缀</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> normalizedPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">processPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getOrCreateTransport</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">normalizedPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SSE_PROTOCOL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createSseTransport</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">normalizedPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> messageEndPoint</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getOrCreateTransport</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> normalizedPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> protocol</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                       </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name namespace" style="opacity:0.7">java</span><span class="token class-name namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token class-name namespace" style="opacity:0.7">util</span><span class="token class-name namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token class-name namespace" style="opacity:0.7">function</span><span class="token class-name namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token class-name">Supplier</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> transportFactory</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取复合Transport实例</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">CompositeTransportProvider</span><span class="token plain"> compositeTransport </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getOrCreateCompositeTransport</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">normalizedPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">T</span><span class="token plain"> transport </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">protocol</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">SSE_PROTOCOL</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> compositeTransport</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSseTransport</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">STREAMABLE_HTTP_PROTOCOL</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">T</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> compositeTransport</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getStreamableHttpTransport</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果缓存中没有该实例，则需要重新创建</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">transport</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 调用createSseTransport()方法，创建一个新的transport并存储</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            transport </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> transportFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 创建McpAsyncServer，并注册transport</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">addTransportToSharedServer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">normalizedPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> protocol</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> transport</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> transport</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="111-transport注册">1.1.1 Transport注册<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Mcp-Server-Plugin#111-transport%E6%B3%A8%E5%86%8C" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h5>
<ul>
<li class=""><code>createSseTransport()</code> 方法</li>
</ul>
<blockquote>
<p>该方法在 <code>getOrCreateMcpServerTransport()</code> 方法被调用，用于创建 Transport</p>
</blockquote>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuMcpServerManager</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">ShenyuSseServerTransportProvider</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createSseTransport</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> normalizedPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> messageEndPoint</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> messageEndpoint </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> normalizedPath </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> messageEndPoint</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuSseServerTransportProvider</span><span class="token plain"> transportProvider </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuSseServerTransportProvider</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">objectMapper</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">objectMapper</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sseEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">normalizedPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">messageEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">messageEndpoint</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 向Manager的routeMap中注册transportProvider的两个函数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">registerRoutes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">normalizedPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> messageEndpoint</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> transportProvider</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">handleSseConnection</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> transportProvider</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">handleMessage</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> transportProvider</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="112-mcpserver注册">1.1.2 mcpServer注册<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Mcp-Server-Plugin#112-mcpserver%E6%B3%A8%E5%86%8C" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h5>
<ul>
<li class=""><code>addTransportToSharedServer()</code> 方法</li>
</ul>
<blockquote>
<p>该方法在 <code>getOrCreateMcpServerTransport()</code> 方法被调用，用于创建 McpServer 并保存</p>
</blockquote>
<p>该方法创建了一个新的 McpServer并存储到 <code>sharedServerMap</code> 中，并将上一步得到的 TransportProvider 存入 <code>compositeTransportMap</code> 中</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuMcpServerManager</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">addTransportToSharedServer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> normalizedPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> protocol</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token plain"> transportProvider</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取或者创建并注册 McpServer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">getOrCreateSharedServer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">normalizedPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 将新增的传输协议存进compositeTransportMap中</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        compositeTransport</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addTransport</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">protocol</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> transportProvider</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">McpAsyncServer</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getOrCreateSharedServer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> normalizedPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> sharedServerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">computeIfAbsent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">normalizedPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> path </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 获取传输协议</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">CompositeTransportProvider</span><span class="token plain"> compositeTransport </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getOrCreateCompositeTransport</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 选择Server拥有的能力</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> capabilities </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">McpSchema</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">ServerCapabilities</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">tools</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">logging</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 创建McpServer并存储</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">McpAsyncServer</span><span class="token plain"> server </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">McpServer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">async</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">compositeTransport</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">serverInfo</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"MCP Shenyu Server (Multi-Protocol)"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"1.0.0"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">capabilities</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">capabilities</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">tools</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Lists</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newArrayList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> server</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="12-tools注册">1.2 Tools注册<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Mcp-Server-Plugin#12-tools%E6%B3%A8%E5%86%8C" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ul>
<li class=""><code>handlerRule()</code> 方法 工作内容如下</li>
</ul>
<ol>
<li class="">捕捉用户在 Tool 上的填写的 tool 配置信息，这些信息将全部用于 tool 的构建</li>
<li class="">序列化创建 <code>ShenyuMcpServerTool</code> 获取 tool 信息</li>
</ol>
<blockquote>
<p>注意 <code>ShenyuMcpServerTool</code> 也是 Shenyu 存储 tool 信息的工具，和 <code>McpServerTool</code> 没有继承关系</p>
</blockquote>
<ol start="3">
<li class="">调用 <code>addTool()</code> 方法， 利用该 tool 信息创建 tool，并根据 SelectorId 将 tool 注册到与之匹配的 McpServer 中</li>
</ol>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">McpServerPluginDataHandler</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">PluginDataHandler</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handlerRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token plain"> ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">s </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 序列化一个新的 ShenyuMcpServerTool</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ShenyuMcpServerTool</span><span class="token plain"> mcpServerTool </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">s</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuMcpServerTool</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 缓存mcpServerTool</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">CACHED_TOOL</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">cachedHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CacheKeyUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INST</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> mcpServerTool</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 获取并构建 mcp schema</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">McpServerToolParameter</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> parameters </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> mcpServerTool</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getParameters</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">String</span><span class="token plain"> inputSchema </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">JsonSchemaUtil</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createParameterSchema</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">parameters</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ShenyuMcpServer</span><span class="token plain"> server </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">CACHED_SERVER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">obtainHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getSelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">server</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 向Manager的sharedServerMap中存储Tool信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                shenyuMcpServerManager</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addTool</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">server</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">mcpServerTool</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> mcpServerTool</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        mcpServerTool</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getDescription</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        mcpServerTool</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequestConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        inputSchema</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class=""><code>addTool()</code>方法</li>
</ul>
<blockquote>
<p>该方法被 <code>handlerRule()</code> 方法调用，用于新增工具</p>
</blockquote>
<p>该方法做了下述工作</p>
<ol>
<li class="">将上一步传来的 tool 信息转换为 <code>shenyuToolDefinition</code> 对象</li>
<li class="">利用转换来的 <code>shenyuToolDefinition</code> 对象创建 <code>ShenyuToolCallback</code> 对象</li>
</ol>
<blockquote>
<p><code>ShenyuToolCallback</code> 重写了 <code>ToolCallBack</code> 的 <code>call()</code> 方法，并将该 <code>call()</code> 方法注册到了 <code>AsyncToolSpecification</code> 中，
此后调用 tool 的 <code>call()</code> 方法，则实际会调用这个重写的 <code>call()</code> 方法</p>
</blockquote>
<ol start="3">
<li class="">将 <code>ShenyuToolCallback</code> 转换为 <code>AsyncToolSpecification</code> 并注册到相关的 mcpServer 中</li>
</ol>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">McpServerPluginDataHandler</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">PluginDataHandler</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">addTool</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> serverPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> name</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> description</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> requestTemplate</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> inputSchema</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> normalizedPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">normalizeServerPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">serverPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建Definition对象</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ToolDefinition</span><span class="token plain"> shenyuToolDefinition </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuToolDefinition</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">description</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">description</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">requestConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">requestTemplate</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">inputSchema</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">inputSchema</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuToolCallback</span><span class="token plain"> shenyuToolCallback </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuToolCallback</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuToolDefinition</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取到先前注册的 McpServer， 并向其中注册Tool</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">McpAsyncServer</span><span class="token plain"> sharedServer </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> sharedServerMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">normalizedPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">AsyncToolSpecification</span><span class="token plain"> asyncToolSpecification </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">McpToolUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toAsyncToolSpecifications</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuToolCallback</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            sharedServer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addTool</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">asyncToolSpecification</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">block</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>到此为止，服务注册分析完毕</p>
<p>服务注册一图览
<img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/Mcp-server-register-zh-87a3e3bf2133de216e36e9609dcd5aad.png" width="1607" height="595" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-插件调用">2. 插件调用<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Mcp-Server-Plugin#2-%E6%8F%92%E4%BB%B6%E8%B0%83%E7%94%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>客户端先后会发送后缀为 <code>/sse</code> 和 <code>/message</code> 的两种消息，这两种消息都会被 <code>Shenyu McpServer plugin</code> 捕捉，<code>Shenyu McpServer plugin</code>
会对 <code>/sse</code> 消息和 <code>/message</code> 消息做不同处理。收到 <code>/sse</code> 消息时 plugin 会创建 session 对象并保存，最后返回 session id
供 message 消息使用。收到 <code>/message</code> 消息时，会根据 <code>/message</code> 消息携带的 method 信息，选择执行的方法
如：获取工作列表，工具调用，获取资源列表等等</p>
<ul>
<li class=""><code>doExecute()</code> 方法 工作内容如下</li>
</ul>
<ol>
<li class="">路径匹配，判断 mcp plugin 是否注册该路径</li>
<li class="">调用 <code>routeByProtocol()</code> 方法，根据请求协议选择合适的处理方案</li>
</ol>
<blockquote>
<p>本篇是对 sse 请求方式的解析，因此接着进入 <code>handleSseRequest()</code> 方法</p>
</blockquote>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">McpServerPlugin</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractShenyuPlugin</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doExecute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                   </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                   </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                   </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> uri </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRawPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 判断 Mcp 插件是否注册了该路由规则，没有则不执行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">shenyuMcpServerManager</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">canRoute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerRequest</span><span class="token plain"> request </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ServerRequest</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> messageReaders</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 根据 uri 判断路由协议，选择对应的处理方案</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">routeByProtocol</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">routeByProtocol</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                       </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                       </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerRequest</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                       </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                       </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> uri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">isStreamableHttpProtocol</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleStreamableHttpRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">isSseProtocol</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 处理sse请求</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleSseRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>handlerSseRequest()</code> 方法</p>
<blockquote>
<p>该方法由 <code>routeByProtocol()</code> 方法调用，根据请求后缀判断客户端是要创建 session 还是调用工具</p>
</blockquote>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">McpServerPlugin</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractShenyuPlugin</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleSseRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerRequest</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> uri</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuMcpServer</span><span class="token plain"> server </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">McpServerPluginDataHandler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CACHED_SERVER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">obtainHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> messageEndpoint </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> server</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessageEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取传输者</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuSseServerTransportProvider</span><span class="token plain"> transportProvider</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> shenyuMcpServerManager</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getOrCreateMcpServerTransport</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uri</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> messageEndpoint</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 根据请求的后缀判断是 sse 连接请求还是 message 调用请求</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uri</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">endsWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">messageEndpoint</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">setupSessionContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleMessageEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> transportProvider</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleSseEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> transportProvider</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="21-客户端发送-sse-请求">2.1 客户端发送 sse 请求<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Mcp-Server-Plugin#21-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%8F%91%E9%80%81-sse-%E8%AF%B7%E6%B1%82" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<blockquote>
<p>如果我们客户端发送的是后缀为 <code>/sse</code> 的请求，那么将会执行 <code>handleSseEndpoint()</code> 方法</p>
</blockquote>
<ul>
<li class=""><code>handleSseEndpoint()</code> 方法主要做了如下工作</li>
</ul>
<ol>
<li class="">配置 sse 请求头</li>
<li class="">调用 <code>ShenyuSseServerTransportProvider</code> 的 <code>createSseFlux()</code> 创建 sse 流</li>
</ol>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">McpServerPlugin</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractShenyuPlugin</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleSseEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                         </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuSseServerTransportProvider</span><span class="token plain"> transportProvider</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                         </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerRequest</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 配置 sse 请求头</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">configureSseHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 创建 sse 流</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">writeWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">transportProvider</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createSseFlux</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class=""><code>createSseFlux()</code> 方法</li>
</ul>
<blockquote>
<p>该方法被 <code>handleSseEndpoint()</code>调用 主要用于创建并保存 session</p>
</blockquote>
<ol>
<li class="">创建 session ，创建 session 的工厂在创建 session 时会将一系列 handler 注册到 session 中，这些 handler 是真正执行
callTool 的对象</li>
<li class="">将 session 保存，session复用</li>
<li class="">将 session id 作为 endpoint 的请求参数返回给客户端，在调用 message 方法时会使用该 endpoint</li>
</ol>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuSseServerTransportProvider</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">McpServerTransportProvider</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Flux</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ServerSentEvent</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">createSseFlux</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerRequest</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Flux</span><span class="token punctuation" style="color:#393A34">.</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ServerSentEvent</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sink </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">WebFluxMcpSessionTransport</span><span class="token plain"> sessionTransport </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">WebFluxMcpSessionTransport</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sink</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 创建 McpServerSession 并暂存插件链信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">McpServerSession</span><span class="token plain"> session </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> sessionFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sessionTransport</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">String</span><span class="token plain"> sessionId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> session</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    sessions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sessionId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> session</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// 将 session id等信息传递回客户端</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">String</span><span class="token plain"> endpointUrl </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">baseUrl </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">messageEndpoint </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"?sessionId="</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> sessionId</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">ServerSentEvent</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> endpointEvent </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ServerSentEvent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">event</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">ENDPOINT_EVENT_TYPE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">data</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">endpointUrl</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doOnSubscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">subscription </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LOGGER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"SSE Flux subscribed"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doOnRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">n </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LOGGER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">debug</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"SSE Flux requested {} items"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> n</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="22-客户端发送-message-请求">2.2 客户端发送 message 请求<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Mcp-Server-Plugin#22-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%8F%91%E9%80%81-message-%E8%AF%B7%E6%B1%82" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<blockquote>
<p>如果我们客户端发送的是后缀为 <code>/message</code> 的请求，那么将会执行 把当前 <code>ShenyuPluginChain</code> 信息存入 session 中，并调用 <code>handleMessageEndpoint()</code> 方法，
后续工具调用时会继续执行该插件链，因此 mcp plugin 后的插件会对进入 tool 的请求造成影响</p>
</blockquote>
<ul>
<li class=""><code>handleMessageEndpoint()</code> 方法，调用 <code>ShenyuSseServerTransportProvider</code> 的 <code>handleMessageEndpoint()</code> 方法</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">if (uri.endsWith(messageEndpoint)) {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       setupSessionContext(exchange, chain);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       return handleMessageEndpoint(exchange, transportProvider, request);</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">} </span><br></span></code></pre></div></div>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">McpServerPlugin</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractShenyuPlugin</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleMessageEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                             </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuSseServerTransportProvider</span><span class="token plain"> transportProvider</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                             </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerRequest</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 处理message请求</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> transportProvider</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handleMessageEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flatMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">writeWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">just</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">bufferFactory</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">wrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">responseBody</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class=""><code>handleMessageEndpoint()</code> 方法</li>
</ul>
<blockquote>
<p>该方法由 <code>McpServerPlugin.handleMessageEndpoint()</code> 调用，将请求交给 session 处理</p>
</blockquote>
<p>session 的 <code>handler()</code> 方法会对 message 的不同，而进行对应的操作
例如 ： 当 message 中 method 是 "tools/call" 时，则会使用工具调用的 handler() 执行 <code>call()</code> 方法调用工具
相关源码在此不过多赘述</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuSseServerTransportProvider</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">McpServerTransportProvider</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MessageHandlingResult</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleMessageEndpoint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerRequest</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取到session</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> sessionId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">queryParam</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"sessionId"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">McpServerSession</span><span class="token plain"> session </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> sessions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sessionId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">bodyToMono</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flatMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">body </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">McpSchema</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">JSONRPCMessage</span><span class="token plain"> message </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">McpSchema</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">deserializeJsonRpcMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">objectMapper</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> body</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> session</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">handle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">message</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>至此 <code>Shenyu Mcp Plugin</code> 服务调用源码分析完毕</p>
<p>流程图一览
<img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/Mcp-server-execute-zh-9cf2daaf68b9189ce0d70536f72f73b8.png" width="1038" height="648" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-工具调用">3. 工具调用<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Mcp-Server-Plugin#3-%E5%B7%A5%E5%85%B7%E8%B0%83%E7%94%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<blockquote>
<p>如果客户端传递的消息是调用工具的消息，那么 session 将使用工具调用的 handler() 并执行 tool 的 <code>call()</code> 方法，
在服务注册中，我们说明了 tool 在被调用时，实际执行的是 <code>ShenyuToolCallback()</code> 的 <code>call()</code> 方法</p>
</blockquote>
<p>因此执行工具调用时会执行以下方法</p>
<ul>
<li class=""><code>call()</code> 主要工作内容如下</li>
</ul>
<ol>
<li class="">获取 session id</li>
<li class="">获取 <code>requestTemplate</code> 即 shenyu 提供的额外功能的配置信息</li>
<li class="">获取上一步暂存的 shenyu 插件链，并将工具调用的信息交给插件链继续执行</li>
<li class="">异步等待工具响应</li>
</ol>
<p>插件链执行完成后，会将调用 tool 请求真正的发送到 tool 所在的服务之中</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuToolCallback</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ToolCallback</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> input</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ToolContext</span><span class="token plain"> toolContext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 从 mcp 请求中提取 sessionId</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">McpSyncServerExchange</span><span class="token plain"> mcpExchange </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">extractMcpExchange</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">toolContext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> sessionId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">extractSessionId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">mcpExchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 提取requestTemplate信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> configStr </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">extractRequestConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuTool</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 利用sessionId 获取到先前暂存的插件执行链</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> originExchange </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getOriginExchange</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sessionId</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getPluginChain</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">originExchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 执行工具调用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">executeToolCall</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">originExchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> sessionId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> configStr</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> input</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">executeToolCall</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> originExchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                   </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                   </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> sessionId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                   </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> configStr</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                   </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> input</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">CompletableFuture</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> responseFuture </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">CompletableFuture</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> decoratedExchange </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildDecoratedExchange</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                originExchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> responseFuture</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> sessionId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> configStr</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> input</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 执行插件链，调用实际工具</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">decoratedExchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">subscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 等待响应</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> responseFuture</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">DEFAULT_TIMEOUT_SECONDS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SECONDS</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>至此Shenyu MCP Plugin 工具调用分析完毕</p>
<p><img decoding="async" loading="lazy" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA1AAAACFCAYAAABVABkwAAAadElEQVR4Xu2cfbAkVXmH2Y+iqICFf0gwQbIYBcSkREUtKhXkQxNjPhRlgd27y5cKEi3LuCwfUQSUJAQTYEEIsSBEhDJ+VISwgElg9y7GuLtUAsVWqpKq/MH+EaGoEGB3pRJW2A5vyzv78vbpnjN9Z3rOmX6eqqfu9DmnT/d0n3Nmfnfm3n0KAAAAAAAAiGIfXwAAAAAAAABhCFAAAAAAAACREKAAAAAAAAAiIUABAAAAAABEQoACAAAAAACIhAAFAAAAAAAQCQEKAAAAAAAgEgIUAAAAAABAJAQoAAAAAACASAhQAAAAAAAAkRCgAAAAAAAAIiFAAQAAAAAAREKAAgAAAAAAiIQABQAAAAAAEAkBCgAAAAAAIBICFAAAAAAAQCQEKAAAAAAAgEgIUAAAAAAAAJEQoAAAAAAAACIhQAEAAAAAAERCgAIAAAAAAIgkiQC1efOW4qyzzymWLTusWLp0abFkyRLEiXngga8t3ve+9xe33vpXfihCxqy/997io6csLw4++PWVe47YtQcd9PPFhz58cvG9u+4q9uzZ44drb3jmmWeKS794efG2t7292G+//SrXCbFLZQzKWLz0i5eVYxOgLVMPUF+49LJin332QZyKJ554UvHEE0/4YQmZcfY5H6/cW8RUnFt1hh+yveDuu/+ueN3rDqpcD8QUlLF518tjFKANUw1Q8lspHci/8Zu/Vdx2+zeLH25+pPjnLY8iTsz19z9YfPoznxuMvWOOeXevf0OcO6tWnzG4l6evWFV86zt3V+45Ytd+52/XF3OrzxqMzVOWn+qH7kyzYcPGwXNfdtgbi6uuvqbY+NCWynVC7FIZgzIWZUzq+JSxCjAqUwtQWx9+eDB4L/n8ZcVzP3kRsVPv+/uN5cf5MgbXXnixH6KQAd+4487BOnLjX9xSuceI0/Zrt94+GKO33HKrH8Izy9FHv6N8ziee9P7iiad2VK4L4jSVMSljU8bo0W9/hx++AEOZWoD6xLnnDRZXP7ARu3LdDTeX4/CA17zGD1HIgOOOO768f+ee96nKvUVMxc989oJynMqn3X3gnnvWD0LjY//2n5XrgZiCMjZ1nMqYBRiFqQWoNx9+RDlo//KWr1cGNWJXPrvrp4NPoR57bJsfpp3wo81bi81btr6qzG9bpH1XNJ3HtHnhhRcGL37zP9haubeIqbjlX7YNxuqOHTv8UJ45PrdmbflcT/7I8sq1QExJGaMyVmXMAozC1ALUz+2/fzloN2zaXBnQiF165JFHlWNx4/y8H6adcPrcmcV119842JbHUhZCAs1pK8N140aOtexNRyUbop588snBm9IfP/Vc5b4ipuIzO3cPxurj27f7oTxzrFg5Vz7XNWsvqVwLxJSUMSpjdcXKVX4YAzRCgMLe+5a3vPVnY3HjdP6QdCEBStpOKuDkFKD4GwtMWfmkexCgHn/cD+WZY+XLb0bluV5w4R9WrgViSsoYlbEqYxZgFAhQ2HtzClBSbgPNJAMOAQpxPBKgENOUAAVtIUBh7x1HgJLQo8HH/42SBBCtD31iNEqAkkAjaJ+yrfv74zYdU7Hn7dsQoBDHIwEKMU0JUNAWAhT23oUGKA0yGkZWrDprEDo0hNigoiFIiQ1Q0peW62MNUDYA6TH1uHI++tii+9vzsm0IUIjjkQCFmKYEKGgLAQp770IClA1Isfj2sQEq9ClRKOBooLJoyKvbDpURoBDHIwEKMU0JUNAWAhT23oUEqFBYqUO+YqchpU2A8oFHy3zACZX5cuk/9N/8pM21675aPiZAIY5HAhRimhKgoC0EKOy9kw5QGpo0OLUJUPbrexYfcJpCjz2uDUoWOQYBCnG89ilAvfTSSwQozEYCFLSFAIW9dyEBKhR2LKH6NgFKtkNBJhRwfP+23H4CRYBC7Ma+BagVK+aKRYsWFWsv+kLlWiCmJAEK2kKAwt670AAlIaOOUJjxZTEBqu4Yvi/B9yf4MBQ6b9/Gb6cGAQpzkQCFmKYEKGgLAQp770IClCCBRYOGKOFEA4wGFS3XtsMClLTRf0su+/pApWif0kbb6/5arts+VIXa+OOE9ksFAhTmIgEKMU0JUNAWAhT23oUGKKEuHAm2XLWf6qy74abKV/Tstq+zaLjyx7Xl8m/M/Tkp0kYNtdFglSIEKMzFPgWoF198kQCF2UiAgrYQoLD3jiNATZKmANVnCFCYi30MUIsXLy4uvJgAhWlLgIK2EKCw96YcoJq+vtd3CFCYi30KUMKqVWcQoDALCVDQFgIU9t6UA5QQ+modEKAwH/sYoOQrfGvWXvLyc99duR6IqUiAgrYQoLD3ph6gIAwBCnOxbwFqbm41AQqzkAAFbSFAYe8lQOUJAQpzsd8B6qeV64GYigQoaAsBCnsvASpPCFCYi30LUPJmVJ4rAQpTlwAFbSFAYe8lQOUJAQpzsa8BSt6c+muBmJIEKGgLAQp7LwEqTwhQmIsEKMQ0JUBBWwhQ2HsJUHlCgMJcJEAhpikBCtpCgMLeS4DKEwIU5iIBCjFNCVDQFgIU9l4CVJ4QoDAXCVCIaUqAgrYQoLD3EqDyhACFuUiAQkxTAhS0hQCFvZcAlScEKMxFAhRimhKgoC0EKOy9BKg8IUBhLhKgENOUAAVtIUBh7yVA5QkBCnORAIWYpgQoaAsBCnsvASpPCFCYiwQoxDQlQEFbehGgduz632LnrucxQ/29nIQEqDxpClDMeZymMv7seCRAjdcdu/6vcs1xtpV77sfBOCRAQVsIUJi0/l5OQgJUnhCgMFUJUAQoHK8EKEgNAhQmrb+Xk5AAlQ6XX355eS/m5+d9VQUCFKbqrAUomY9y7jI/YyBA4bglQO1l1PkIk4EAhUnr7+UkJEClgwaomBBFgMJUnbUAZedlzJs2AhSOWwLUXkadjzAZCFCYtP5eTkICVFqccMIJUSFqGgFqw/wPKmWT0B6nq2P2QX9dx3FttQ/b16wFKGGUN22pBKhx3N/cHOdz9n357Qc3PlTZZxz644gEqFczynwcF8vedFSxecvWwfbpc2eWeq67/sZBufy8dt1XXYvZoDcBSibkn/7ZdZVJKUp5aMK2Vfobd5/jsotzk76Xn766Ut5Gfy8nIQEqPWyI2lhzX6YRoOQFZJS502a+Xf3n6141f+Sx3V/71H4n9SZmksp5h67JqNdqFKVfuX+6Lde17jUhVrvW2XOfxQAlXHHFFVFv2roMUHVzTMrG9To0Dnfs/Ek5V+389XPZ7zOqfoxb2xzHrne+b+nrlNNWVfZZqHX3jQBVJXY+jovYAGXbSZgiQI2ZrgOUTEq5qf4FUxcFX95Wmfj6wiw/6xazadjluY3revp7OQkJUGky7JOoYQHKvrkdl7EBSo9t51vsuQwLULpe2Xk8rvk2Kf1aU/cmSa+XLx+H/g3gOI5l743eE3k8qwFKiPnNd1cBys8x/wY/NMampQQoOadTV5wxOFdRn0PMujJMP8ZFOaauEYPr9ZVrK/uGtOud71v6I0BNn5j5OC7k/g8LUFLvy2S/WaT3AcouwH7CjqpfYLTMt5uGKZ9bk/5eTkICVLo0haiUA1RoTYnZT4wJUHZb2vu5nZr+/OreJIWu27j0a+BCjxUaX9r/LAcoYdibti4ClL+fek/0cd0Ym5QSkOzPUJ363I5dZZC6egHjL6S/Jhs3/VNlvRhFAlQeDJuPHgk5NghZtC5UHxOgZNvvu+6Gm8pPomaNXgUoDVF2Umqo8i+k2lbrpUxfMEN1Wu/799p97SLh+w6dq+9/lL6k3PfnrevP19nnXLePP5ZvZxd0PVdtY+v9vZyEdQFKFiKcvvrC4ENUU4DaMP/DwXjzY9OPRTtOfb0d6zqu/Zu0QdtXfqvr52lI2U+OHTrOqAEqVNb0HHydPVedi7odei5+f9vW1+n+Vu0jdO398W1/ol837DH9dfL76/WuO1bo/OuOZdv740l5bICS8ezHey7aX27ItmVaAcrfC73Hev/9113r7rc8VnVfeSxBSObnGw//lTIEaXsJKqetPHMQjL5yzfVlubR/YMOmsswety5ASfumcejP2df7ayLnHZpndf35tlKmc8r3LftJgKo7V/88fN++XveVn7atbncdoPx4T92m+ahIiNHrLUFHfjbV+a/eSdmwAOXbCBKgfLtZoFcBShdBnagygX2ZaF9Y7YukLiB12zrZfZlfCOx2U1/+Bd4uhjF9+QWr6dz0WoT6s8fy18OW60IrynFsX/a56HlovdTZ87LH9vdyEoYClCxA9o07pqF9YWgKUHbO6zjTsWbHbDkuzddZ/Nz3c1DGqY5zPy9C5XXaueLnw6gByh/PPwc/t/RNj85lPxft89X9bb19znau+uPqOfo+9Dz0vKyh49t9bJ209c/N19tz1fa23re35+/b+rXTH8+WxQaoWVpn7C83ughQcr3101d/H/Re+PFhPzGRbTtv7P0M7WvHgwSo8j6/8smShCcJSrItj696eU2Rx6MGKCmXc5IApmHKnod+oqTbg/qaX95IX3YOhbTXTq6n3Za+6uaxv0b+XO311Dp7Ln5frZMyvS/2cZcBatOmTZXxnZseCTVyze0nQTboSLmt00Blke2YAOXZsvXhSrtZoHqVO2JaAUpfSGVC6vawia7afVU7wX07u0DY4/l2/rHtu27/UF+6uNnH3lHOTfuw1872JeV118oeX/a1x9J6+1xsvT22v5eTMBSgBP8bHpyO9kUh9hOougDlx2to3th6HeOh/evGf+i4Tfr5GhOgpMzOY79+2f5tvT9f375pLob2t33bx1bfh7a1z8M/H9+H3Ue3/bn6en+u/jzs/lLn75l9Pnp+tt7fF7tPbIDK+RMoOy9l29JVgLL3zo8deezvWdP4sO3r9tX2GjQ0QP3yEb8aDFBSJ6EnJkBp2JK+bJkcR/rU4/rzknoNhn6M++c4TD/O7f6+b3tcu7+9B5W6V4Ken6tWvfZ6PD1+lwFKyG1uNs1HQQKMjKNRkOtvA5Pf9gFKgpK08dSV507vApRMRJ24+tO+UIYWTrXuRdaX2fZ2UZfHIev61n1sX7Y8ZKhtyFHOTdQFz79pqCu3+8pjv4jbhdYvuvb8/b2chHUBCqbPQv4Gys9N/e2tHYd2fDbNQR2/fizb8a9fD/LHDSl96L76U/v1b5JCc8uej/0ETeeOV46hdbYvO9f0WHVzsa5vf66+zB9DrLtG/vjyWNtq33VtQ+dq+/Zldn+9B966NUrL7LXUY0h5bIDKFfuGLfRmrcsA5e+vvad+jEm9tBs2lpv2tduvuufm0ygfoKTefuVv8FW/l+e6lkl72U/DkpZpqPJhStWxq+dSN8brtPNL/8GF1tnn7PuW/YYFKO178POVtUqP589F97H3RMu7DlA5MWw+CjEBSj+Fstd/1ABV90mT7Dtr9DJA2QVDt+2iayetVRdKW9a0EPi+pd+6xSzUt93f1w/rq+45hPoe1p/fJ9S3L/ePfd9SpguzX3Tt+ft7OQkJUGnSFJ6EUQOUH3d2rNk3Vba9L/P7q3b8+3289pihfkcJUH7eDTt2ORcDgUu37ZoQqvfnHVLq7Zz2fehx/L0R/X62je+nad0IXeOm/f119Ppj6T51ZbMcoGLerE0jQPl7EhpjdkyUc8HdP9tP0772WH5+SggZFqBEeTNrA5TUy37+EygJUNK2LkBJ33WfQPmv5Hn9HNNz1W37nH3f0m9TgPJzprxe5hMof31tO7039vwJUGFi5qMgwcb/TZNFg5P81JAk26MGKGnjqSvPnV4GKNEuDLoQ2jq7XbeADOtHtItrqN4eI7Sg6D5+kfbPx/flzzN0bLvADesv1LctF+218AutPbY8tvV+obXH8PdyEhKg0mNYeBKGBaiYeSCP7ZsAP/dlbNatG6Hxb/v180nKZB9/Xrqt/YUClD0n21bb+3o/1+052ADl56I/71B9Xd9+nfDXzbb1x1Gb1iR/Lv66+Ovqr8Ow/X17q2+r/fkyaSfnMasBKvbNWhcBqrz+7t9x6/XX++PHmJ07oftn723Tvnb/0Ni2/UrgkTUmFKCuuvqaQdASn31uZ/n3VfLVPimXbf2nFBqgpL4cY65e9vdzQM/bP0/7abmt88/bPmfft7T1f1Nm2/vjlnPIfYXPrxl15yBlBKgqsfNRCP1Nk0Xq/D9/8GV+2wcoIXSMpk+mcqa3ASq0EPqFQNrbRUDfFKh+gdD60L6qr7eLk1+wVW3vy5v6km3bdiHnVvec68r1nJv6riys7jrq/v5eTkICVFrEhCdhWIDScWjHl53DUmfHeaheftr6si/3NZTQmI4Z86quTXoc/cP4pjcU9py0LPQc9dh+bbDnpHPN79tUb/uoWyfsOepz0Ofhn5MqZX4d0f38ufi2dt3QY9jz1J++3m/b51B3LD2eL5N2Uj6LAWqUN2tdBCi5zhIe7L219yM0xvy49GOjbs6F9tUy386PO9kOBajykyoXoET5FEpCkuwvPzUcifo1v8Pe/NZgvRxD/8GFltk576+Tr/Nf4dNy3bb76vMK9av19jrIz9Avb/y+/tprOwLUqxllPgqhfyLhP23ydVLmA5Rv44OR30fgv/CNma4DlCwUfvFTY8v1zYM+9vW2XUx9qNyXNbVvqguV2fbD6sdRHiqrK68r8/dyEhKg0iE2PAkxAappzIXKY+pteVO7YfW+n7o6v+3rmspC5ba9/JQXvLp6/3hY33Xlvq6u3bCyusexZb7eb2uZL/fbqr120kZfH2YtQMlcHOXNWhcByt8vf4/qyvw9rGsXKvP7yv0Olfv2oTZS5sOTKuVSL1+pG1dd6DnZutBjv2378OW+T98+ZKi+rowAtZdR56OiIcqqYUcDkwQdDUry2IYh/ymW/dqfLbPbgu9nVuhNgPITt40yie1vRnDy+ns5CQlQ6aC/VRsWnoSYAIXNypoWClAYp/x2XH9zbt9Mz1qA0nkZ+2atywA1LXk/0K0EqL2MOh89EmbqAk1dueLr/Xbsp1KzAAFqBFkwu9ffy0lIgMoTAtTCJUAtXPvVIy2btQA1KrMeoPRrZ/6TEpycBKh8sJ9Kyc9h//0vVwhQI8qC2a3+Xk5CAlSeEKDGI2va+CVAzXaAYs50LwEqH+zfVtnHs0YvAhRikwSoPGkKUIgpSYBCTFMCFLSFAIW9lwCVJwQozEUCFGKaEqCgLQQo7L0EqDwhQGEuEqAQ05QABW0hQGHvJUDlCQEKc5EAhZimBChoCwEKey8BKk8IUJiLBCjENCVAQVsIUNh7CVB5QoDCXCRAIaYpAQraQoDC3kuAyhMCFOYiAQoxTQlQ0BYCFPZeAlSeEKAwFwlQiGlKgIK2EKCw9xKg8oQAhblIgEJMUwIUtIUAhb2XAJUnBCjMRQIUYpoSoKAtBCjsvQSoPCFAYS4SoBDTlAAFbSFAYe8lQOUJAQpzkQCFmKYEKGgLAQp7LwEqTwhQmIsEKMQ0JUBBWwhQ2HsJUHlCgMJcJEAhpikBCtpCgMLeS4DKEwIU5iIBCjFNCVDQFgIU9l4CVJ4QoDAXCVCIaUqAgrYQoLD3EqDyhACFuUiAQkxTAhS0hQCFvZcAlScEKMxFAhRimhKgoC0EKOy9BKg8IUBhLhKgENOUAAVtIUBh7yVA5QkBCnORAIWYpgQoaAsBCnsvASpPCFCYiwQoxDQlQEFbCFDYewlQeUKAwlwkQCGmKQEK2kKAwt5LgMoTAhTmIgEKMU0JUNAWAhT2XgJUnhCgMBcJUIjp+eyu3cWatZcQoKAVBCjsvQSoPCFAYS4SoBDTUwPUokWLilWrzvDDGKARAhT2XgJUnhCgMBcJUIjpSYCChUCAwt5LgMoTAhTmIgEKMT0JULAQphag9j/ggHKBfXD+R5VBjdilRx55VDkWN87P+2EKCWMD1I+feq5yXxFT8Zmduwdjdfv27X4ozxwrVs6Vz1XenPprgZiKMi//YM1FZYCaW7XaD2OARqYWoA4/4shygb35a7dVBjViV/7PjheKfffdtxyL27Zt88MUEmb37r1vSvkkG1N288OPDcbqzp07/VCeOdZcsLZ8rh/68Ecr1wIxFeX1/3d/7+Ri8eLFxYUXXeyHMUAjUwtQ55//qXKBfe/xJ1YGNWJXXrPuxnIcHnjga/0QhQw4/vgTyvv3sU98snJvEVPx9z/92XKcvuc9x/ohPJPce+99g8D4r4/9e+V6IKbgI9v+oxyjS5YsKe6///t+GAM0MrUA9cijjw4WWD7mx2l49/p/KJYuXVqOwYsv+bwfopABf/Otbw/WkWvX3VS5x4jT9qabbx2M0dv++ut+CM8sx7zr3eVz/vXjji+2/9d/V64L4jSVMfneE04qv773zne+yw9fgKFMLUAJX/rylYMXFvkkSr7OJ1/F2fjQFsSJ+d3v3Vuce97PPgEVjz321/zQhIw4+5yPD+7lyR9ZXtx+57cr9xyxa+/45neL5aeuGIxN+bugPrFp00OD5/4Lv3hIccWX/6T4/j9uqlwnxC6VMfilK68qDnnDoWV4kvG5YeN8sWfPHj+EARqZaoASbIhC7NoPfOCDxdNPP+2HJWTGeZ88v3JvEVPx7HM+5odsL5CvRR1yyBsq1wNxWkpo0uAkY/Oe9esJT9CKqQcoQb7OJ38TJf9YQv47n/yLc8RJefDBry8++Nu/U3zjjjv9UISMeeCBB4uVc6uLZcsOq9xzxK499NBfKk47fUVx3/33+6HaK55//vniyj/64/Lvv+RvTf11QuxSGYMyFmVM7tq1yw9XgGiSCFAAAAAAAAA5QIACAAAAAACIhAAFAAAAAAAQCQEKAAAAAAAgEgIUAAAAAABAJAQoAAAAAACASAhQAAAAAAAAkRCgAAAAAAAAIiFAAQAAAAAAREKAAgAAAAAAiIQABQAAAAAAEAkBCgAAAAAAIBICFAAAAAAAQCQEKAAAAAAAgEgIUAAAAAAAAJEQoAAAAAAAACIhQAEAAAAAAERCgAIAAAAAAIiEAAUAAAAAABAJAQoAAAAAACASAhQAAAAAAEAkBCgAAAAAAIBICFAAAAAAAACREKAAAAAAAAAi+X+qWpaxlGLVEwAAAABJRU5ErkJggg==" width="848" height="133" class="img_ev3q"></p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-小结">4. 小结<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Mcp-Server-Plugin#4-%E5%B0%8F%E7%BB%93" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>本文源码分析从 mcp 服务注册开始，到 mcp 插件的服务调用，再到 tool 的调用。
mcpServer 插件让 shenyu 成为一个功能强大，集中管理的 mcpServer。</p>
<hr>]]></content>
        <author>
            <name>yusiheng</name>
            <uri>https://github.com/478320</uri>
        </author>
        <category label="plugin" term="plugin"/>
        <category label="mcp" term="mcp"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Param-Mapping插件源码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Param-Mapping-Plugin</id>
        <link href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Param-Mapping-Plugin"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[开始前，可以参考 这篇文章 运行shenyu网关]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p>开始前，可以参考 <a class="" href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo">这篇文章</a> 运行shenyu网关</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="正文">正文<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Param-Mapping-Plugin#%E6%AD%A3%E6%96%87" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>先看一下这个插件的结构，如下图。</p>
<p><img decoding="async" loading="lazy" alt="param-mapping-structure" src="https://shenyu.apache.org/zh/assets/images/param-mapping-structure-1d2b4243e835eeff74fc6ea114dcbee7.png" width="416" height="282" class="img_ev3q"></p>
<p>猜测：handler是用来做数据同步的；strategy中文意思是策略，可能是对各种请求体做了适配，应该是这个插件的重点；<code>ParamMappingPlugin</code> 应该是 <code>ShenyuPlugin</code> 的实现。</p>
<p>首先，看一下 <code>ParamMappingPlugin</code> ，里面主要是对 <code>doExecute</code> 方法的重写。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doExecute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// paramMappingHandle判断是否为空</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 根据首部行中的contentType确定请求体类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">HttpHeaders</span><span class="token plain"> headers </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHeaders</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">MediaType</span><span class="token plain"> contentType </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> headers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContentType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  	</span><span class="token comment" style="color:#999988;font-style:italic">// *</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">match</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contentType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> paramMappingHandle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">
<p>match方法是根据contentType返回对应的 <code>Operator</code></p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Operator</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">match</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MediaType</span><span class="token plain"> mediaType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MediaType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APPLICATION_JSON</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isCompatibleWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">mediaType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> operatorMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MediaType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APPLICATION_JSON</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MediaType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APPLICATION_FORM_URLENCODED</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isCompatibleWith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">mediaType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> operatorMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MediaType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APPLICATION_FORM_URLENCODED</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> operatorMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DEFAULT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>从match方法的代码可以看出，目前有 <code>DefaultOperator</code>、<code>FormDataOperator</code>、<code>JsonOperator</code>三种，支持 <code>x-www-form-urlencoded</code> 和 <code>json</code> 两种格式的请求体。</p>
</li>
</ul>
<p>那么我们就来看一下上面三种Operator究竟是怎么样的吧。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="一defaultoperator">一、DefaultOperator<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Param-Mapping-Plugin#%E4%B8%80defaultoperator" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>虚晃一枪，它的apply方法只是继续执行插件链，并没有实质功能。当请求体没有匹配到Operator时，就会通过 <code>DefaultOperator</code> 跳过。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="二formdataoperator">二、FormDataOperator<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Param-Mapping-Plugin#%E4%BA%8Cformdataoperator" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>这个类是用来处理 <code>x-www-form-urlencoded</code> 格式的请求体的。</p>
<p>主要是看apply方法，但是这个apply方法长得有点奇怪。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> shenyuPluginChain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ParamMappingHandle</span><span class="token plain"> paramMappingHandle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getFormData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">switchIfEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">defer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">just</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">LinkedMultiValueMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flatMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">multiValueMap </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>省略号中的代码是对请求体的处理，如下。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 判空</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">multiValueMap</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> multiValueMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> shenyuPluginChain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 将form-data转化成json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">String</span><span class="token plain"> original </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">multiValueMap</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"get from data success data:{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> original</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// *修改请求体*</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">String</span><span class="token plain"> modify </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">operation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">original</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> paramMappingHandle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">modify</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> shenyuPluginChain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 将修改后的json，转换成LinkedMultiValueMap。注意一下这一行，后面会提到！</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token class-name">LinkedMultiValueMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> modifyMap </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toLinkedMultiValueMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">modify</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">BodyInserter</span><span class="token plain"> bodyInserter </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">BodyInserters</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">modifyMap</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// 修改exchange中的请求体，然后继续执行插件链</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> bodyInserter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insert</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cachedBodyOutputMessage</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">BodyInserterContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">defer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> shenyuPluginChain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">mutate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">request</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ModifyServerHttpRequestDecorator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">httpHeaders</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> cachedBodyOutputMessage</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onErrorResume</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Function</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Throwable</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> throwable </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">release</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cachedBodyOutputMessage</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> throwable</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<blockquote>
<p>PS: 省略的部分是设置请求头等操作。</p>
</blockquote>
<p>上面比较重要的应该是打星的修改请求体，也就是 <code>operation</code> 方法的调用。这里因为参数类型的原因，会先调用 <code>Operator</code> 接口的默认方法（而不是 <code>FormDataOperator</code> 重写的）。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">operation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> jsonValue</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ParamMappingHandle</span><span class="token plain"> paramMappingHandle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">DocumentContext</span><span class="token plain"> context </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">JsonPath</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">jsonValue</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 调用重写的operation方法，添加addParameterKey</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">operation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> paramMappingHandle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 对设置的replacedParameterKey进行替换</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">paramMappingHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getReplaceParameterKeys</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        paramMappingHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getReplaceParameterKeys</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">info </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">renameKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> info</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> info</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 对设置的removeParameterKey进行删除</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">paramMappingHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRemoveParameterKeys</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        paramMappingHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRemoveParameterKeys</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">info </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">delete</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">jsonString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>梳理下来可以发现，这里引入的json工具<a href="https://github.com/json-path/JsonPath" target="_blank" rel="noopener noreferrer" class="">JsonPath</a>使得请求体的加工变得简单、清晰很多。</p>
<p><strong>另外，我们可以注意到 <code>FormDataOperator</code> 重写了 <code>operation(DocumentContext, ParamMappingHandle)</code> 方法。</strong></p>
<p><strong>为什么要重写呢？</strong> 接口中有对应处理addParameterKey的默认方法啊。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// Operator接口中的默认方法</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">operation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DocumentContext</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ParamMappingHandle</span><span class="token plain"> paramMappingHandle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">paramMappingHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAddParameterKeys</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        paramMappingHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAddParameterKeys</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">info </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> info</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> info</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//不同之处</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// FormDataOperator重写的方法</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">operation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DocumentContext</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ParamMappingHandle</span><span class="token plain"> paramMappingHandle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">paramMappingHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAddParameterKeys</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        paramMappingHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAddParameterKeys</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">info </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> info</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Arrays</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">asList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>实际上，在 <code>FormDataOperator#apply</code> 中有这么一行（前面有提到）：<code>LinkedMultiValueMap&lt;String, String&gt; modifyMap = GsonUtils.getInstance().toLinkedMultiValueMap(modify);</code></p>
<p>这一行是将修改后的json转换成 <code>LinkedMultiValueMap</code>，<code>GsonUtils#toLinkedMultiValueMap</code> 如下。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">LinkedMultiValueMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">toLinkedMultiValueMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">GSON</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">json</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">TypeToken</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">LinkedMultiValueMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>而 <code>LinkedMultiValueMap</code> 类中的属性 <code>targetMap</code> 定义为：<code>private final Map&lt;K, List&lt;V&gt;&gt; targetMap</code></p>
<p>因此，json字符串中的value必须是列表形式的，不然Gson就会抛出转换错误的异常，这也就是为什么 <code>FormDataOperator</code> 要重写operator方法。</p>
<p><strong>那么为什么要用 <code>LinkedMultiValueMap</code> 呢？</strong></p>
<p>回到 <code>FormDataOperator#apply</code> 方法的第一行 <code>exchange.getFormData</code> 。而SpringMVC中，<code>DefaultServerWebExchange#getFormData</code> 的返回值类型就是 <code>Mono&lt;MultiValueMap&lt;String, String&gt;&gt;</code> ，而 <code>LinkedMultiValueMap</code> 是 <code>MultiValueMap</code> 的子类。并且，<code>getFormData</code> 方法就是针对 <code>x-www-form-urlencoded</code> 格式的请求体的。</p>
<p><img decoding="async" loading="lazy" alt="param-mapping-getFormData" src="https://shenyu.apache.org/zh/assets/images/param-mapping-getFormData-04b664908cd5f52d149eb1098d5648c9.png" width="667" height="134" class="img_ev3q"></p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="三jsonoperator">三、JsonOperator<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Param-Mapping-Plugin#%E4%B8%89jsonoperator" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>显然，这个类是用来处理Json格式的请求体的。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">apply</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> shenyuPluginChain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ParamMappingHandle</span><span class="token plain"> paramMappingHandle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ServerRequest</span><span class="token plain"> serverRequest </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ServerRequest</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">MESSAGE_READERS</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> mono </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> serverRequest</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">bodyToMono</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">switchIfEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">defer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">just</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flatMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">originalBody </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"get body data success data:{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> originalBody</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 调用默认的operation方法修改请求体</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> modify </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">operation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">originalBody</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> paramMappingHandle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">just</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">modify</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">BodyInserter</span><span class="token plain"> bodyInserter </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">BodyInserters</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">fromPublisher</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">mono</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//处理首部行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">CachedBodyOutputMessage</span><span class="token plain"> outputMessage </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">CachedBodyOutputMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> headers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 修改exchange中的请求体，然后继续执行插件链</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> bodyInserter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">insert</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">outputMessage</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">BodyInserterContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">then</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Mono</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">defer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">ServerHttpRequestDecorator</span><span class="token plain"> decorator </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ModifyServerHttpRequestDecorator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">headers</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> outputMessage</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> shenyuPluginChain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">mutate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">request</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">decorator</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onErrorResume</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Function</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Throwable</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> throwable </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">release</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">outputMessage</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> throwable</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>JsonOperator</code> 的处理流程与 <code>FormDataOperator</code> 大致类似。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="总结">总结<a href="https://shenyu.apache.org/zh/blog/Plugin-SourceCode-Analysis-Param-Mapping-Plugin#%E6%80%BB%E7%BB%93" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>最后，用一张图来简单总结一下。</p>
<p><img decoding="async" loading="lazy" alt="param-mapping-summary" src="https://shenyu.apache.org/zh/assets/images/param-mapping-summary-490cf9ee499bf9efc03d0c963b39118c.jpg" width="930" height="771" class="img_ev3q"></p>]]></content>
        <author>
            <name>Kunshuai Zhu</name>
            <uri>https://github.com/JooKS-me</uri>
        </author>
        <category label="Param-Mapping" term="Param-Mapping"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[注册中心实现原理之Http注册]]></title>
        <id>https://shenyu.apache.org/zh/blog/RegisterCenter-SourceCode-Analysis-Http-Register</id>
        <link href="https://shenyu.apache.org/zh/blog/RegisterCenter-SourceCode-Analysis-Http-Register"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[Apache ShenYu 是一个异步的，高性能的，跨语言的，响应式的 API 网关。]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p><a href="https://shenyu.apache.org/zh/docs/index" target="_blank" rel="noopener noreferrer" class="">Apache ShenYu</a> 是一个异步的，高性能的，跨语言的，响应式的 <code>API</code> 网关。</p>
</blockquote>
<p>在<code>ShenYu</code>网关中，注册中心是用于将客户端信息注册到<code>shenyu-admin</code>，<code>admin</code>再通过数据同步将这些信息同步到网关，网关通过这些数据完成流量筛选。客户端信息主要包括<code>接口信息</code>和<code>URI信息</code>。</p>
<blockquote>
<p>本文基于<code>shenyu-2.5.0</code>版本进行源码分析，官网的介绍请参考 <a href="https://shenyu.apache.org/zh/docs/design/register-center-design" target="_blank" rel="noopener noreferrer" class="">客户端接入原理</a> 。</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-注册中心原理">1. 注册中心原理<a href="https://shenyu.apache.org/zh/blog/RegisterCenter-SourceCode-Analysis-Http-Register#1-%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E5%8E%9F%E7%90%86" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>当客户端启动时，读取接口信息和<code>uri信息</code>，通过指定的注册类型，将数据发送到<code>shenyu-admin</code>。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/register-center-6df3139bde6babdb3360f928f93bf737.png" width="1628" height="526" class="img_ev3q"></p>
<p>图中的注册中心需要用户指定使用哪种注册类型，<code>ShenYu</code>当前支持<code>Http</code>、<code>Zookeeper</code>、<code>Etcd</code>、<code>Consul</code>和<code>Nacos</code>进行注册。具体如何配置请参考 <a href="https://shenyu.apache.org/zh/docs/user-guide/property-config/register-center-access" target="_blank" rel="noopener noreferrer" class="">客户端接入配置</a> 。</p>
<p><code>ShenYu</code>在注册中心的原理设计上引入了<code>Disruptor</code>，<code>Disruptor</code>队列在其中起到数据与操作解耦，利于扩展。如果注册请求过多，导致注册异常，也有数据缓冲作用。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/shenyu-register-center-679a8ce3a7173b5f7a29f312448efa47.png" width="1975" height="507" class="img_ev3q"></p>
<p>如图所示，注册中心分为两个部分，一是注册中心客户端<code>register-client</code>，负责处理客户端数据读取。另一个是注册中心服务端<code>register-server</code>，负责处理服务端（就是<code>shenyu-admin</code>）数据写入。通过指定注册类型进行数据发送和接收。</p>
<ul>
<li class="">客户端：通常来说就是一个微服务，可以是<code>springmvc</code>，<code>spring-cloud</code>，<code>dubbo</code>，<code>grpc</code>等。</li>
<li class=""><code>register-client</code>：注册中心客户端，读取客户接口和<code>uri</code>信息。</li>
<li class=""><code>Disruptor</code>：数据与操作解耦，数据缓冲作用。</li>
<li class=""><code>register-server</code>：注册中心服务端，这里就是<code>shenyu-admin</code>，接收数据，写入数据库，发数据同步事件。</li>
<li class="">注册类型：指定注册类型，完成数据注册，当前支持<code>Http</code>、<code>Zookeeper</code>、<code>Etcd</code>、<code>Consul</code>和<code>Nacos</code>。</li>
</ul>
<p>本文分析的是使用<code>Http</code>的方式进行注册，所以具体的处理流程如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/shenyu-register-center-http-540b66ff202c41000b463cfae8403699.png" width="2169" height="621" class="img_ev3q"></p>
<p>在客户端，数据出队列后，通过<code>http</code>传输数据，在服务端，提供相应的接口，接收数据，然后写入队列。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-客户端注册�流程">2. 客户端注册流程<a href="https://shenyu.apache.org/zh/blog/RegisterCenter-SourceCode-Analysis-Http-Register#2-%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%B3%A8%E5%86%8C%E6%B5%81%E7%A8%8B" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>当客户端启动后，根据相关配置，读取属性信息，然后写入队列。以官方提供的 <a href="https://github.com/apache/incubator-shenyu/tree/master/shenyu-examples/shenyu-examples-http" target="_blank" rel="noopener noreferrer" class="">shenyu-examples-http</a> 为例，开始源码分析。官方提供的例子是一个由<code>springboot</code>构建的微服务。注册中心的相关配置可以参考官网  <a href="https://shenyu.apache.org/zh/docs/user-guide/property-config/register-center-access" target="_blank" rel="noopener noreferrer" class="">客户端接入配置</a> 。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="21-加载配置读取属性">2.1 加载配置，读取属性<a href="https://shenyu.apache.org/zh/blog/RegisterCenter-SourceCode-Analysis-Http-Register#21-%E5%8A%A0%E8%BD%BD%E9%85%8D%E7%BD%AE%E8%AF%BB%E5%8F%96%E5%B1%9E%E6%80%A7" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>先用一张图串联下注册中心客户端初始化流程：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/client-register-init-zh-40a0219a500b6637453b6ad0daf1bf87.png" width="1517" height="763" class="img_ev3q"></p>
<p>我们分析的是通过<code>http</code>的方式进行注册，所以需要进行如下配置：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">register</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">registerType</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">serverLists</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//localhost</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">9095</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">props</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">username</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> admin</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">password</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">123456</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">client</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">props</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">contextPath</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /http</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">appName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8189</span><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">isFull</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">false</span><br></span></code></pre></div></div>
<p>每个属性表示的含义如下：</p>
<ul>
<li class=""><code>registerType</code>: 服务注册类型，填写 <code>http</code>。</li>
<li class=""><code>serverList</code>: 为<code>http</code>注册类型时，填写<code>Shenyu-Admin</code>项目的地址，注意加上<code>http://</code>，多个地址用英文逗号分隔。</li>
<li class=""><code>username</code>: <code>Shenyu-Admin</code>用户名</li>
<li class=""><code>password</code>: <code>Shenyu-Admin</code>用户对应的密码</li>
<li class=""><code>port</code>: 你本项目的启动端口，目前<code>springmvc/tars/grpc</code>需要进行填写。</li>
<li class=""><code>contextPath</code>: 为你的这个<code>mvc</code>项目在<code>shenyu</code>网关的路由前缀， 比如<code>/order</code> ，<code>/product</code> 等等，网关会根据你的这个前缀来进行路由。</li>
<li class=""><code>appName</code>：你的应用名称，不配置的话，会默认取 <code>spring.application.name</code> 的值。</li>
<li class=""><code>isFull</code>: 设置 <code>true</code> 代表代理你的整个服务，<code>false</code>表示代理你其中某几个<code>controller</code>；目前适用于<code>springmvc/springcloud</code>。</li>
</ul>
<p>项目启动后，会先加载配置文件，读取属性信息，生成相应的<code>Bean</code>。</p>
<p>首先读取到的配置文件是 <code>ShenyuSpringMvcClientConfiguration</code>，它是<code>shenyu</code> 客户端<code>http</code>注册配置类，通过<code>@Configuration</code>表示这是一个配置类，通过<code>@ImportAutoConfiguration</code>引入其他配置类。创建<code>SpringMvcClientEventListener</code>，主要处理元数据和 <code>URI</code> 信息。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * shenyu 客户端http注册配置类</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ImportAutoConfiguration</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientCommonBeanConfiguration</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.register.enabled"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> matchIfMissing </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> havingValue </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"true"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClientConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 创建SpringMvcClientEventListener，主要处理元数据和URI信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">SpringMvcClientEventListener</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">springHttpClientEventListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuClientConfig</span><span class="token plain"> clientConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                                     </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token plain"> shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">       </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">SpringMvcClientEventListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clientConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p><code>ShenyuClientCommonBeanConfiguration</code>是<code>shenyu</code>客户端通用配置类，会创建注册中心客户端通用的<code>bean</code>。</p>
<ul>
<li class="">创建<code>ShenyuClientRegisterRepository</code>，通过工厂类创建而成。</li>
<li class="">创建<code>ShenyuRegisterCenterConfig</code>，读取<code>shenyu.register</code>属性配置。</li>
<li class="">创建<code>ShenyuClientConfig</code>，读取<code>shenyu.client</code>属性配置。</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * shenyu客户端通用配置类</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuClientCommonBeanConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 创建ShenyuClientRegisterRepository，通过工厂类创建而成。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuRegisterCenterConfig</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepositoryFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">config</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// 创建ShenyuRegisterCenterConfig，读取shenyu.register属性配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.register"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuRegisterCenterConfig</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 创建ShenyuClientConfig，读取shenyu.client属性配置</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuClientConfig</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">shenyuClientConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuClientConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="22-用于注册的-httpclientregisterrepository">2.2 用于注册的 HttpClientRegisterRepository<a href="https://shenyu.apache.org/zh/blog/RegisterCenter-SourceCode-Analysis-Http-Register#22-%E7%94%A8%E4%BA%8E%E6%B3%A8%E5%86%8C%E7%9A%84-httpclientregisterrepository" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>上面的配置文件中生成的<code>ShenyuClientRegisterRepository</code>是客户端注册的具体实现，它是一个接口，它的实现类如下。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/shenyu-client-register-repository-dba8edf50af1be31d8b53c9573b1e015.png" width="3020" height="620" class="img_ev3q"></p>
<ul>
<li class=""><code>HttpClientRegisterRepository</code>：通过<code>http</code>进行注册；</li>
<li class=""><code>ConsulClientRegisterRepository</code>：通过<code>Consul</code>进行注册；</li>
<li class=""><code>EtcdClientRegisterRepository</code>：通过<code>Etcd</code>进行注册；</li>
<li class=""><code>NacosClientRegisterRepository</code>：通过<code>nacos</code>进行注册；</li>
<li class=""><code>ZookeeperClientRegisterRepository</code>通过<code>Zookeeper</code>进行注册。</li>
</ul>
<p>具体是哪一种方式，是通过<code>SPI</code>进行加载实现的，实现逻辑如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 加载 ShenyuClientRegisterRepository</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepositoryFactory</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">ShenyuClientRegisterRepository</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">REPOSITORY_MAP</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ConcurrentHashMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 创建 ShenyuClientRegisterRepository</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">newInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuRegisterCenterConfig</span><span class="token plain"> shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token constant" style="color:#36acaa">REPOSITORY_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">containsKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRegisterType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 通过SPI的方式进行加载，类型由registerType决定</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ExtensionLoader</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getExtensionLoader</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getJoin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRegisterType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//执行初始化操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ShenyuClientShutdownHook</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">REPOSITORY_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRegisterType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">REPOSITORY_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRegisterType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>加载类型通过<code>registerType</code>指定，也就是我们在配置文件中指定的类型：</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">register</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">registerType</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">serverLists</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//localhost</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">9095</span><br></span></code></pre></div></div>
<p>我们指定的是<code>http</code>，所以会去加载<code>HttpClientRegisterRepository</code>。对象创建成功后，执行的初始化方法<code>init()</code>如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Join</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpClientRegisterRepository</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuRegisterCenterConfig</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">username </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">USER_NAME</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">password </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PASS_WORD</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">serverList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Lists</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newArrayList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Splitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">on</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">","</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">split</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getServerLists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setAccessToken</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 暂时省略其他逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>读取配置文件中的<code>username</code>、<code>password</code>和<code>serverLists</code>，即<code>sheenyu-admin</code>的访问账号、密码和地址信息，为后续数据发送做准备。类注解<code>@Join</code>用于<code>SPI</code>的加载。</p>
<blockquote>
<p><code>SPI</code> 全称为 <code>Service Provider Interface</code>, 是 <code>JDK</code> 内置的一种服务提供发现功能, 一种动态替换发现的机制。</p>
<p><a href="https://github.com/apache/incubator-shenyu/tree/master/shenyu-spi" target="_blank" rel="noopener noreferrer" class="">shenyu-spi</a> 是<code>Apache ShenYu</code>网关自定义的<code>SPI</code>扩展实现，设计和实现原理参考了<code>Dubbo</code>的 <a href="https://dubbo.apache.org/zh/docs/v2.7/dev/impls/" target="_blank" rel="noopener noreferrer" class="">SPI扩展实现</a> 。</p>
</blockquote>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="23--构建-元数据-和-uri信息-的-springmvcclienteventlistener">2.3  构建 元数据 和 URI信息 的 SpringMvcClientEventListener<a href="https://shenyu.apache.org/zh/blog/RegisterCenter-SourceCode-Analysis-Http-Register#23--%E6%9E%84%E5%BB%BA-%E5%85%83%E6%95%B0%E6%8D%AE-%E5%92%8C-uri%E4%BF%A1%E6%81%AF-%E7%9A%84-springmvcclienteventlistener" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>创建 <code>SpringMvcClientEventListener</code>，负责客户端 <code>元数据</code> 和 <code>URI</code> 数据的构建和注册，它的创建是在配置文件中完成。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ImportAutoConfiguration</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientCommonBeanConfiguration</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ConditionalOnProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.register.enabled"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> matchIfMissing </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> havingValue </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"true"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClientConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">// ......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//  创建 SpringMvcClientEventListener</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">SpringMvcClientEventListener</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">springHttpClientEventListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuClientConfig</span><span class="token plain"> clientConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                                      </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token plain"> shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">SpringMvcClientEventListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clientConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class=""><code>SpringMvcClientEventListener</code>继承了<code>AbstractContextRefreshedEventListener</code></li>
</ul>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/shenyu-client-event-listener-0cd56409c59f2546a285a6426f9c8fee.png" width="4618" height="500" class="img_ev3q"></p>
<p><code>AbstractContextRefreshedEventListener</code>是一个抽象类，它实现了<code>ApplicationListener</code>接口，并重写了<code>onApplicationEvent()</code>方法，当有Spring事件发生后，该方法会执行。它的实现目前有八种，每一种表示对应的RPC调用协议的 <code>元数据</code> 和<code>URI</code> 信息的注册。</p>
<ul>
<li class=""><code>AlibabaDubboServiceBeanListener</code>：处理使用<code>Alibaba Dubbo</code>协议；</li>
<li class=""><code>ApacheDubboServiceBeanListener</code>：处理使用<code>Apacge Dubbo</code>协议；</li>
<li class=""><code>GrpcClientEventListener</code>：处理使用<code>grpc</code>协议；</li>
<li class=""><code>MotanServiceEventListener</code>：处理使用<code>Mortan</code>协议；</li>
<li class=""><code>SofaServiceEventListener</code>：处理使用<code>Sofa</code>协议；</li>
<li class=""><code>SpringMvcClientEventListener</code>：处理使用<code>http</code>协议；</li>
<li class=""><code>SpringWebSocketClientEventListener</code>：处理使用<code>websocket</code>协议；</li>
<li class=""><code>TarsServiceBeanEventListener</code>：处理使用<code>Tars</code>注册类型；</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 实现了ApplicationListener接口</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractContextRefreshedEventListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">A</span><span class="token generics"> </span><span class="token generics keyword" style="color:#00009f">extends</span><span class="token generics"> </span><span class="token generics class-name">Annotation</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ApplicationListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ContextRefreshedEvent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//构造函数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">AbstractContextRefreshedEventListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PropertiesConfig</span><span class="token plain"> clientConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                 </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token plain"> shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 读取 shenyu.client.http 配置信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Properties</span><span class="token plain"> props </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> clientConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// appName 应用名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">appName </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">APP_NAME</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// contextPath上下文路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">contextPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CONTEXT_PATH</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">UriUtils</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">repairData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">orElse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">appName</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">String</span><span class="token plain"> errorMsg </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"client register param must config the appName or contextPath"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">errorMsg</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuClientIllegalArgumentException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">errorMsg</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ipAndPort </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">IP_PORT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// host信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">host </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HOST</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// port 客户端端口信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">port </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PORT</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 开始事件发布</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 当有上下文刷新事件ContextRefreshedEvent发生时，该方法会执行</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onApplicationEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ContextRefreshedEvent</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//保证该方法的内容只执行一次</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">registered</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">compareAndSet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApplicationContext</span><span class="token plain"> context </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getApplicationContext</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取声明RPC调用的类</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> beans </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getBeans</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MapUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">beans</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建URI数据并注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildURIRegisterDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> beans</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建元数据并注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        beans</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">handle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 交给不同的子类实现</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"all"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token class-name">URIRegisterDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildURIRegisterDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ApplicationContext</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                          </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> beans</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> beanName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token plain"> bean</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> clazz </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getCorrectedClass</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bean</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取当前bean的对应shenyu客户端的注解（对应不同的RPC调用注解不一样，像http的就是@ShenyuSpringMvcClient,而像SpringCloud的则是@ShenyuSpringCloudClient）</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">A</span><span class="token plain"> beanShenyuClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">AnnotatedElementUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findMergedAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getAnnotationType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 根据bean获取对应的path（不同子类实现不一样）</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> superPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildApiSuperPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> beanShenyuClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果包含Shenyu客户端注解或者path中包括'*'，表示注册整个类的接口</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">beanShenyuClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">contains</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"*"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 构建类的元数据，发送注册事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">handleClass</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> bean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> beanShenyuClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取当前bean的所有方法</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Method</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> methods </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ReflectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUniqueDeclaredMethods</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clazz</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历方法</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Method</span><span class="token plain"> method </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> methods</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 注册符合条件的方法</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">handleMethod</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> beanShenyuClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 构建类元数据并注册的默认实现</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleClass</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                               </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token plain"> bean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                               </span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">A</span><span class="token plain"> beanShenyuClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                               </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildMetaDataDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> beanShenyuClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">pathJoin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 构建方法元数据并注册的默认实现</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleMethod</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token plain"> bean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token annotation punctuation" style="color:#393A34">@Nullable</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">A</span><span class="token plain"> beanShenyuClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Method</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果方法上有Shenyu客户端注解，就表示该方法需要注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">A</span><span class="token plain"> methodShenyuClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">AnnotatedElementUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findMergedAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getAnnotationType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">methodShenyuClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 构建元数据，发送注册事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildMetaDataDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> methodShenyuClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildApiPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> methodShenyuClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 交给不同子类实现</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildMetaDataDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">T</span><span class="token plain"> bean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                            </span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token class-name">A</span><span class="token plain"> shenyuClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                            </span><span class="token class-name">String</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                            </span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                            </span><span class="token class-name">Method</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>在构造函数中主要是读取属性配置。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">client</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">props</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">contextPath</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /http</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">appName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8189</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">isFull</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">false</span><br></span></code></pre></div></div>
<p>最后，执行了<code>publisher.start()</code>，开始事件发布，为注册做准备。</p>
<ul>
<li class="">ShenyuClientRegisterEventPublisher</li>
</ul>
<p><code>ShenyuClientRegisterEventPublisher</code>通过单例模式实现，主要是生成元数据和<code>URI</code>订阅器（后续用于数据发布），然后启动<code>Disruptor</code>队列。提供了一个共有方法<code>publishEvent()</code>，发布事件，向Disruptor队列发数据。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterEventPublisher</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 私有变量</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterEventPublisher</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterEventPublisher</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">DisruptorProviderManage</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataTypeParent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> providerManage</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 公开静态方法</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return ShenyuClientRegisterEventPublisher instance</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterEventPublisher</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Start方法执行</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param shenyuClientRegisterRepository shenyuClientRegisterRepository</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token plain"> shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 创建客户端注册工厂类</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RegisterClientExecutorFactory</span><span class="token plain"> factory </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">RegisterClientExecutorFactory</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 添加元数据订阅器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        factory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addSubscribers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuClientMetadataExecutorSubscriber</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//  添加URI订阅器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        factory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addSubscribers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuClientURIExecutorSubscriber</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 启动Disruptor队列</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        providerManage </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DisruptorProviderManage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">factory</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        providerManage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">startup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 发布事件，向Disruptor队列发数据</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param data the data</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataTypeParent</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">DisruptorProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataTypeParent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> provider </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> providerManage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProvider</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        provider</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>AbstractContextRefreshedEventListener</code>的构造函数逻辑分析完成了，主要是读取属性配置，创建<code>元数据</code>和<code>URI</code>订阅器，启动<code>Disruptor</code>队列。</p>
<p><code>onApplicationEvent()</code>方法是有<code>Spring</code>事件发生时会执行，这里的参数是<code>ContextRefreshedEvent</code>，表示上下文刷新事件。当<code>Spring</code>容器就绪后执行此处逻辑：先构建<code>URI</code>数据并注册，再构建元数据并注册，</p>
<blockquote>
<p><code>ContextRefreshedEvent</code>是<code>Spring</code>内置事件。<code>ApplicationContext</code>被初始化或刷新时，该事件被触发。这也可以在 <code>ConfigurableApplicationContext</code>接口中使用 <code>refresh()</code> 方法来发生。此处的初始化是指：所有的<code>Bean</code>被成功装载，后处理<code>Bean</code>被检测并激活，所有<code>Singleton Bean</code> 被预实例化，<code>ApplicationContext</code>容器已就绪可用。</p>
</blockquote>
<p>再来看<code>AbstractContextRefreshedEventListener</code>的http实现<code>SpringMvcClientEventListener</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">SpringMvcClientEventListener</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractContextRefreshedEventListener</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Object</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">ShenyuSpringMvcClient</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics"> </span><span class="token generics keyword" style="color:#00009f">extends</span><span class="token generics"> </span><span class="token generics class-name">Annotation</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> mappingAnnotation </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ArrayList</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token plain"> isFull</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> protocol</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 构造函数</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">SpringMvcClientEventListener</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">PropertiesConfig</span><span class="token plain"> clientConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token plain"> shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">super</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clientConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Properties</span><span class="token plain"> props </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> clientConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取 isFull</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">isFull </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parseBoolean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">IS_FULL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">FALSE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toString</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 表示是http协议的实现</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">protocol </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> props</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PROTOCOL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuClientConstants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        mappingAnnotation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        mappingAnnotation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RequestMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">Object</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getBeans</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApplicationContext</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 配置属性，如果 isFull=true 的话，表示注册整个微服务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Boolean</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TRUE</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">isFull</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">getPublisher</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MetaDataRegisterDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">contextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">appName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">getAppName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PathUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">decoratorPathWithSlash</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RpcTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">HTTP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">enabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ruleName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 否则获取带Controller注解的bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBeansWithAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Controller</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 构造URI数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">URIRegisterDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildURIRegisterDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ApplicationContext</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                 </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">Object</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> beans</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildApiSuperPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@Nullable</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token plain"> beanShenyuClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果有带上Shenyu客户端注解，则优先取注解中的不为空的path属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">beanShenyuClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">beanShenyuClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> beanShenyuClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 如果有带上RequestMapping注解，且path属性不为空，则返回path数组的第一个值</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RequestMapping</span><span class="token plain"> requestMapping </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">AnnotationUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">RequestMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">requestMapping</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">ArrayUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">requestMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">requestMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> requestMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 声明http实现的客户端注解是ShenyuSpringMvcClient</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ShenyuSpringMvcClient</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getAnnotationType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleMethod</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token plain"> bean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token annotation punctuation" style="color:#393A34">@Nullable</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token plain"> beanShenyuClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Method</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取当前bean的RequestMapping注解</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RequestMapping</span><span class="token plain"> requestMapping </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">AnnotatedElementUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findMergedAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">RequestMapping</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取当前bean的 ShenyuSpringMvcClient 注解</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token plain"> methodShenyuClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">AnnotatedElementUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findMergedAnnotation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        methodShenyuClient </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">methodShenyuClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> beanShenyuClient </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> methodShenyuClient</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//如果有 ShenyuSpringMvcClient 注解并且包含RequestMapping注解（表示是一个接口），则进行注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">methodShenyuClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">requestMapping</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">getPublisher</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">buildMetaDataDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> methodShenyuClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildApiPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">method</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> superPath</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> methodShenyuClient</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 构造元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildMetaDataDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Object</span><span class="token plain"> bean</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                   </span><span class="token annotation punctuation" style="color:#393A34">@NonNull</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token plain"> shenyuClient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                   </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Class</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> clazz</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                                   </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Method</span><span class="token plain"> method</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>注册逻辑都是通过 <code>publisher.publishEvent()</code>完成。</p>
<p><code>Controller</code>注解和<code>RequestMapping</code>注解是由<code>Spring</code>提供的，这个大家应该很熟悉，不过多赘述。<code>ShenyuSpringMvcClient</code> 注解是由<code>Apache ShenYu</code>提供的，用于注册<code>SpringMvc</code>客户端，它的定义如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * shenyu 客户端接口，用于方法上或类上</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Retention</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RetentionPolicy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">RUNTIME</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Target</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token class-name">ElementType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TYPE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ElementType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">METHOD</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token annotation punctuation" style="color:#393A34">@interface</span><span class="token plain"> </span><span class="token class-name">ShenyuSpringMvcClient</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// path 注册路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@AliasFor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">attribute </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"path"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">value</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// path 注册路径</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@AliasFor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">attribute </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"value"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ruleName 规则名称</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ruleName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// desc 描述信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">desc</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// enabled是否启用</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">enabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// registerMetaData 注册元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain">  </span><span class="token function" style="color:#d73a49">registerMetaData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>它的使用如下：</p>
<ul>
<li class="">注册整个接口</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@RestController</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequestMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/test"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ShenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/test/**"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 表示整个接口注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpTestController</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">注册当前方法</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@RestController</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequestMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/order"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@ShenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/order"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">OrderController</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Save order dto.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param orderDTO the order dto</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the order dto</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@PostMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/save"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ShenyuSpringMvcClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/save"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> desc </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Save order"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 注册当前方法</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">OrderDTO</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">save</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@RequestBody</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">OrderDTO</span><span class="token plain"> orderDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        orderDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"hello world save order"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> orderDTO</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">publisher.publishEvent() 发布注册事件</li>
</ul>
<p>该方法会将数据发送到<code>Disruptor</code>队列中，关于<code>Disruptor</code>队列更多细节这里不做更多介绍，这不影响分析注册的流程。</p>
<p>当数据发送后，<code>Disruptor</code>队列的消费者会处理数据，进行消费。</p>
<ul>
<li class="">QueueConsumer 消费数据</li>
</ul>
<p><code>QueueConsumer</code>是一个消费者，它实现了<code>WorkHandler</code>接口，它的创建过程在<code>providerManage.startup()</code>逻辑中。<code>WorkHandler</code>接口是<code>disruptor</code>的数据消费接口，只有一个方法是<code>onEvent()</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">package</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">com</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token namespace" style="opacity:0.7">lmax</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token namespace" style="opacity:0.7">disruptor</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> </span><span class="token class-name">WorkHandler</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">T</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>QueueConsumer</code>重写了<code>onEvent()</code>方法，主要逻辑是生成消费任务，然后在线程池中去执行。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * </span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 队列消费者</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">QueueConsumer</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">WorkHandler</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataEvent</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// 省略了其他逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEvent</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> t</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">t </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 根据事件类型使用不同的线程池</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ThreadPoolExecutor</span><span class="token plain"> executor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">orderly</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">t</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 通过工厂创建队列消费任务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">QueueConsumerExecutor</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> queueConsumerExecutor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> factory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 保存数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            queueConsumerExecutor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">t</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// help gc</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            t</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 放在线程池中执行 消费任务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            executor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">queueConsumerExecutor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>QueueConsumerExecutor</code>是在线程池中被执行的任务，它实现了<code>Runnable</code>接口，具体的实现类有两个：</p>
<ul>
<li class=""><code>RegisterClientConsumerExecutor</code>：客户端消费者执行器；</li>
<li class=""><code>RegisterServerConsumerExecutor</code>：服务端消费者执行器。</li>
</ul>
<p>顾名思义，一个负责处理客户端任务，一个负责处理服务端任务（服务端就是<code>admin</code>，在下文进行分析）。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/consumer-executor-f7ad67d35abaa5a2fac94ef913445a19.png" width="1310" height="483" class="img_ev3q"></p>
<ul>
<li class="">RegisterClientConsumerExecutor 消费者执行器</li>
</ul>
<p>重写的<code>run()</code>逻辑如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">RegisterClientConsumerExecutor</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics"> </span><span class="token generics keyword" style="color:#00009f">extends</span><span class="token generics"> </span><span class="token generics class-name">DataTypeParent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">QueueConsumerExecutor</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">//...... </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 获取数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token plain"> data </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 根据数据类型调用相应的处理器进行处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        subscribers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">executor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Lists</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newArrayList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>根据不同的数据类型调用不同的处理器去执行相应的任务。数据类型有两种，一个是元数据，记录客户端注册信息。一个是<code>URI</code>数据，记录客户端服务信息。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">//数据类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">enum</span><span class="token plain"> </span><span class="token class-name">DataType</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// URI数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token constant" style="color:#36acaa">URI</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">ExecutorSubscriber#executor() 执行器订阅者</li>
</ul>
<p>执行器订阅者也分为两类，一个是处理元数据，一个是处理<code>URI</code>。在客户端和服务端分别有两个，所以一共是四个。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/executor-subscriber-86d5645d204ad1d05fe12dd30992c8d1.png" width="1732" height="403" class="img_ev3q"></p>
<p>先看元数据处理</p>
<ul>
<li class="">ShenyuClientMetadataExecutorSubscriber#executor()</li>
</ul>
<p>客户端这边对元数据处理逻辑是：遍历元数据信息，调用接口方法<code>persistInterface()</code>完成数据的发布。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuClientMetadataExecutorSubscriber</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ExecutorTypeSubscriber</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">DataType</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">DataType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">executor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaDataRegisterDTOList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> metaDataRegisterDTO </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> metaDataRegisterDTOList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 调用接口方法persistInterface()完成数据的发布</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">persistInterface</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataRegisterDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">ShenyuClientRegisterRepository#persistInterface()</li>
</ul>
<p><code>ShenyuClientRegisterRepository</code>是一个接口，用于表示客户端数据注册，它的实现类目前有五种，每一种就表示一种注册方法。</p>
<ul>
<li class=""><code>ConsulClientRegisterRepository</code>：通过<code>Consul</code>实现客户端注册；</li>
<li class=""><code>EtcdClientRegisterRepository</code>：通过<code>Etcd</code>实现客户端注册；</li>
<li class=""><code>HttpClientRegisterRepository</code>：通过<code>Http</code>实现客户端注册；</li>
<li class=""><code>NacosClientRegisterRepository</code>：通过<code>Nacos</code>实现客户端注册；</li>
<li class=""><code>ZookeeperClientRegisterRepository</code>：通过<code>Zookeeper</code>实现客户端注册；</li>
</ul>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/client-register-repository-61756e3284c1d3a27083b25d393edf9c.png" width="1956" height="473" class="img_ev3q"></p>
<p>从图中可以看出，注册中心的加载是通过<code>SPI</code>的方式完成的。这个在前面提到过了，在客户端通用配置文件中，通过指定配置文件中的属性完成具体的类加载。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 加载 ShenyuClientRegisterRepository</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepositoryFactory</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">ShenyuClientRegisterRepository</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">REPOSITORY_MAP</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ConcurrentHashMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * 创建 ShenyuClientRegisterRepository</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">newInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuRegisterCenterConfig</span><span class="token plain"> shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token constant" style="color:#36acaa">REPOSITORY_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">containsKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRegisterType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 通过SPI的方式进行加载，类型由registerType决定</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ExtensionLoader</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getExtensionLoader</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getJoin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRegisterType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//执行初始化操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ShenyuClientShutdownHook</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">REPOSITORY_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRegisterType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">REPOSITORY_MAP</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRegisterType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>本文的源码分析是基于<code>Http</code>的方式进行注册，所以我们先分析<code>HttpClientRegisterRepository</code>，其他的注册方式后续再分析。<code>HttpClientRegisterRepository</code>继承了<code>FailbackRegistryRepository</code>，而<code>FailbackRegistryRepository</code>本身主要用于对<code>Http</code>注册过程中的失败异常的处理，这里就省略了。</p>
<p>通过<code>http</code>的方式注册很简单，就是调用工具类发送<code>http</code>请求。注册元数据和URI都是调用的同一个方法<code>doRegister()</code>，指定接口和类型就好。</p>
<ul>
<li class=""><code>Constants.URI_PATH</code>的值<code>/shenyu-client/register-metadata</code>：服务端提供的接口用于注册元数据。</li>
<li class=""><code>Constants.META_PATH</code>的值<code>/shenyu-client/register-uri</code>：    服务端提供的接口用于注册URI。</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Join</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">HttpClientRegisterRepository</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">FailbackRegistryRepository</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Logger</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">LOGGER</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">LoggerFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLogger</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">URIRegisterDTO</span><span class="token plain"> uriRegisterDTO</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> username</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> password</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> serverList</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> accessToken</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">HttpClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">HttpClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuRegisterCenterConfig</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">config</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuRegisterCenterConfig</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// admin的用户名</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">username </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">USER_NAME</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// admin的用户名对应的密码</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">password </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProperty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">PASS_WORD</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// admin服务列表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">serverList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Lists</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newArrayList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Splitter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">on</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">","</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">split</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">config</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getServerLists</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 设置访问的token</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setAccessToken</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Persist uri.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param registerDTO the register dto</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doPersistURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">URIRegisterDTO</span><span class="token plain"> registerDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RuntimeUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">listenByOther</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">registerDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPort</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">doRegister</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">registerDTO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI_PATH</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        uriRegisterDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> registerDTO</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doPersistInterface</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> metadata</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">doRegister</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metadata</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_PATH</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_TYPE</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">close</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uriRegisterDTO </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            uriRegisterDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setEventType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">EventType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">DELETED</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">doRegister</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uriRegisterDTO</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI_PATH</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setAccessToken</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> server </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> serverList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Optional</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> login </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RegisterUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doLogin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">username</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> password</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> server</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">concat</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">LOGIN_PATH</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                login</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">accessToken </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">valueOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">v</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Exception</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token constant" style="color:#36acaa">LOGGER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Login admin url :{} is fail, will retry. cause: {} "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> server</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doRegister</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">T</span><span class="token plain"> t</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历admin服务列表（admin可能是集群）</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> server </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> serverList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">String</span><span class="token plain"> concat </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> server</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">concat</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 设置访问token</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">accessToken</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setAccessToken</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">accessToken</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">NullPointerException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"accessToken is null"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// 调用工具类发送 http 请求</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">RegisterUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doRegister</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">GsonUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toJson</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">t</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> concat</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> accessToken</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Exception</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token constant" style="color:#36acaa">LOGGER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Register admin url :{} is fail, will retry. cause:{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> server</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> serverList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">RuntimeException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>将数据序列化后，通过<code>OkHttp</code>发送数据。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">RegisterUtils</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">//...... </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 通过OkHttp发送数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doRegister</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">IOException</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">hasLength</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">accessToken</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOGGER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{} client register error accessToken is null, please check the config : {} "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Headers</span><span class="token plain"> headers </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Headers</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">Builder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Constants</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">X_ACCESS_TOKEN</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> accessToken</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">build</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">OkHttpTools</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">post</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">url</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> headers</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">equals</span><span class="token punctuation" style="color:#393A34">(</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOGGER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{} client register success: {} "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token constant" style="color:#36acaa">LOGGER</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{} client register error: {} "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> type</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>至此，客户端通过<code>http</code>的方式注册元数据的逻辑就分析完了。小结一下：通过读取自定义的注解信息构造元数据，将数据发到<code>Disruptor</code>队列，然后从队列中消费数据，将消费者放到线程池中去执行，最终通过发送<code>http</code>请求到<code>admin</code>。</p>
<p>再来看看 <code>URI</code> 数据的处理</p>
<ul>
<li class="">ShenyuClientURIExecutorSubscriber#executor()</li>
</ul>
<p>主要逻辑是遍历URI数据集合，通过<code>persistURI()</code>方法实现数据注册。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuClientURIExecutorSubscriber</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ExecutorTypeSubscriber</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">DataType</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">DataType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//数据类型是URI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 注册URI数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">executor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> dataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">URIRegisterDTO</span><span class="token plain"> uriRegisterDTO </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> dataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Stopwatch</span><span class="token plain"> stopwatch </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Stopwatch</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">createStarted</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Socket</span><span class="token plain"> ignored </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Socket</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uriRegisterDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHost</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uriRegisterDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPort</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">IOException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> sleepTime </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1000</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token comment" style="color:#999988;font-style:italic">// maybe the port is delay exposed</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">stopwatch</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">elapsed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SECONDS</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token constant" style="color:#36acaa">LOG</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"host:{}, port:{} connection failed, will retry"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                                uriRegisterDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHost</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uriRegisterDTO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPort</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// If the connection fails for a long time, Increase sleep time</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">stopwatch</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">elapsed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SECONDS</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">180</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            sleepTime </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10000</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token class-name">TimeUnit</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">MILLISECONDS</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sleep</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sleepTime</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">InterruptedException</span><span class="token plain"> ex</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        ex</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">printStackTrace</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">//添加hook，优雅停止客户端 </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ShenyuClientShutdownHook</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">delayOtherHooks</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 注册URI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            shenyuClientRegisterRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">persistURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uriRegisterDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>代码中的<code>while(true)</code>循环是为了保证客户端已经成功启动了，通过<code>host</code>和<code>port</code>可以连接上。</p>
<p>后面的逻辑是：添加<code>hook</code>函数，用于优雅停止客户端 。</p>
<p>通过<code>persistURI()</code>方法实现数据注册。整个逻辑也在前面分析过了，最终就是通过<code>OkHttp</code>客户端向<code>shenyu-admin</code>发起<code>http</code>，通过<code>http</code>的方式注册<code>URI</code>。</p>
<p>分析到这里就将客户端的注册逻辑分析完了，将构建的元数据和URI数据发送到<code>Disruptor</code>队列，再从中消费，读取数据，通过<code>http</code>向<code>admin</code>发送数据。</p>
<p>客户端<code>元数据</code>和<code>URI</code>注册流程的源码分析完成了，流程图如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/client-metadata-uri-register-zh-a7094099a530101dee93b172a1bc0254.png" width="1506" height="691" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-服务端注册流程">3. 服务端注册流程<a href="https://shenyu.apache.org/zh/blog/RegisterCenter-SourceCode-Analysis-Http-Register#3-%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%B3%A8%E5%86%8C%E6%B5%81%E7%A8%8B" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="31-注册接口shenyuclienthttpregistrycontroller">3.1 注册接口ShenyuClientHttpRegistryController<a href="https://shenyu.apache.org/zh/blog/RegisterCenter-SourceCode-Analysis-Http-Register#31-%E6%B3%A8%E5%86%8C%E6%8E%A5%E5%8F%A3shenyuclienthttpregistrycontroller" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>从前面的分析可以知道，服务端提供了注册的两个接口：</p>
<ul>
<li class=""><code>/shenyu-client/register-metadata</code>：服务端提供的接口用于注册元数据。</li>
<li class=""><code>/shenyu-client/register-uri</code>：    服务端提供的接口用于注册URI。</li>
</ul>
<p>这两个接口位于<code>ShenyuClientHttpRegistryController</code>中，它实现了<code>ShenyuClientServerRegisterRepository</code>接口，是服务端注册的实现类。它用<code>@Join</code>标记，表示通过<code>SPI</code>进行加载。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// shenuyu客户端接口</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@RequestMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/shenyu-client"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Join</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ShenyuClientHttpRegistryController</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ShenyuClientServerRegisterRepository</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">ShenyuClientServerRegisterPublisher</span><span class="token plain"> publisher</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuClientServerRegisterPublisher</span><span class="token plain"> publisher</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuRegisterCenterConfig</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">publisher </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> publisher</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">close</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">close</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 注册元数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@PostMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/register-metadata"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ResponseBody</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerMetadata</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@RequestBody</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> metaDataRegisterDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publish</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">metaDataRegisterDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// 注册URI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@PostMapping</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/register-uri"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ResponseBody</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">registerURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token annotation punctuation" style="color:#393A34">@RequestBody</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">URIRegisterDTO</span><span class="token plain"> uriRegisterDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publish</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uriRegisterDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>两个注册接口获取到数据好，就调用了<code>publisher.publish()</code>方法，把数据发布到<code>Disruptor</code>队列中。</p>
<ul>
<li class=""><code>ShenyuClientServerRegisterRepository</code>接口</li>
</ul>
<p><code>ShenyuClientServerRegisterRepository</code>接口是服务注册接口，它有五个实现类，表示有五种注册方式：</p>
<ul>
<li class=""><code>ConsulClientServerRegisterRepository</code>：通过<code>Consul</code>实现注册;</li>
<li class=""><code>EtcdClientServerRegisterRepository</code>：通过<code>Etcd</code>实现注册；</li>
<li class=""><code>NacosClientServerRegisterRepository</code>：通过<code>Nacos</code>实现注册；</li>
<li class=""><code>ShenyuClientHttpRegistryController</code>：通过<code>Http</code>实现注册；</li>
<li class=""><code>ZookeeperClientServerRegisterRepository</code>：通过<code>Zookeeper</code>实现注册。</li>
</ul>
<p>具体用哪一种方式，是通过配置文件指定的，然后通过<code>SPI</code>进行加载。</p>
<p>在<code>shenyu-admin</code>中的<code>application.yml</code>文件中配置注册方式，<code>registerType</code>指定注册类型，当用<code>http</code>进行注册时，<code>serverLists</code>不需要填写，更多配置说明可以参考官网  <a href="https://shenyu.apache.org/zh/docs/user-guide/property-config/register-center-access" target="_blank" rel="noopener noreferrer" class="">客户端接入配置</a> 。</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">shenyu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">register</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">registerType</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    serverLists</span><span class="token punctuation" style="color:#393A34">:</span><br></span></code></pre></div></div>
<ul>
<li class="">RegisterCenterConfiguration 加载配置</li>
</ul>
<p>在引入相关依赖和属性配置后，启动<code>shenyu-admin</code>时，会先加载配置文件，和注册中心相关的配置文件类是<code>RegisterCenterConfiguration</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 注册中心配置类</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@Configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">RegisterCenterConfiguration</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 读取配置属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@ConfigurationProperties</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"shenyu.register"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuRegisterCenterConfig</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//创建ShenyuServerRegisterRepository，用于服务端注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Bean</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">destroyMethod </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"close"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">ShenyuServerRegisterRepository</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">shenyuServerRegisterRepository</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuRegisterCenterConfig</span><span class="token plain"> shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ShenyuClientRegisterService</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> shenyuClientRegisterService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 1.从配置属性中获取注册类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> registerType </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRegisterType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 2.通过注册类型，以SPI的方法加载实现类</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">ShenyuClientServerRegisterRepository</span><span class="token plain"> registerRepository </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ExtensionLoader</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getExtensionLoader</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientServerRegisterRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getJoin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">registerType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 3.获取publisher，向Disruptor队列中写数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RegisterClientServerDisruptorPublisher</span><span class="token plain"> publisher </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RegisterClientServerDisruptorPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 4.注册Service， rpcType -&gt; registerService</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">ShenyuClientRegisterService</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> registerServiceMap </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> shenyuClientRegisterService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuClientRegisterService</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 5.事件发布的准备工作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">registerServiceMap</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 6.注册的初始化操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        registerRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">publisher</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> shenyuRegisterCenterConfig</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> registerRepository</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>在配置类中生成了两个<code>bean</code>：</p>
<ul>
<li class="">
<p><code>shenyuRegisterCenterConfig</code>：读取属性配置；</p>
</li>
<li class="">
<p><code>shenyuClientServerRegisterRepository</code>：用于服务端注册。</p>
</li>
</ul>
<p>在创建<code>shenyuClientServerRegisterRepository</code>的过程中，也进行了一系列的准备工作：</p>
<ul>
<li class="">
<p>1.从配置属性中获取注册类型。</p>
</li>
<li class="">
<p>2.通过注册类型，以<code>SPI</code>的方法加载实现类：比如指定的类型是<code>http</code>，就会加载<code>ShenyuClientHttpRegistryController</code>。</p>
</li>
<li class="">
<p>3.获取<code>publisher</code>，向<code>Disruptor</code>队列中写数据。</p>
</li>
<li class="">
<p>4.注册<code>Service</code>， <code>rpcType -&gt; registerService</code>：获取注册的<code>Service</code>，每种<code>rpc</code>都有对应的<code>Service</code>。本文的客户端构建是通过<code>springboot</code>，属于<code>http</code>类型，还有其他客户端类型：<code>dubbo</code>，<code>Spring Cloud</code>，<code>gRPC</code>等。</p>
</li>
<li class="">
<p>5.事件发布的准备工作：添加服务端元数据和<code>URI</code>订阅器，处理数据。并且启动<code>Disruptor</code>队列。</p>
</li>
<li class="">
<p>6.注册的初始化操作：<code>http</code>类型的注册初始化操作就是保存<code>publisher</code>。</p>
</li>
<li class="">
<p>RegisterServerDisruptorPublisher#publish()</p>
</li>
</ul>
<p>服务端向<code>Disruptor</code>队列写入数据的发布者 ，通过单例模式构建。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">RegisterClientServerDisruptorPublisher</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ShenyuClientServerRegisterPublisher</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//私有属性</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RegisterClientServerDisruptorPublisher</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">RegisterClientServerDisruptorPublisher</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">DisruptorProviderManage</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataTypeParent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> providerManage</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//公开静态方法获取实例</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">RegisterServerDisruptorPublisher</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">INSTANCE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">//事件发布的准备工作，添加服务端元数据和URI订阅器，处理数据。并且启动Disruptor队列。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">ShenyuClientRegisterService</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> shenyuClientRegisterService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//服务端注册工厂</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RegisterServerExecutorFactory</span><span class="token plain"> factory </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">RegisterServerExecutorFactory</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//添加URI数据订阅器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        factory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addSubscribers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">URIRegisterExecutorSubscriber</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuClientRegisterService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//添加元数据订阅器</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        factory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addSubscribers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">MetadataExecutorSubscriber</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuClientRegisterService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//启动Disruptor队列</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        providerManage </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DisruptorProviderManage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">factory</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        providerManage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">startup</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 向队列中写入数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">publish</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataTypeParent</span><span class="token plain"> data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">DisruptorProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataTypeParent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> provider </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> providerManage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProvider</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        provider</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singleton</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 批量向队列中写入数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">publish</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics"> </span><span class="token generics keyword" style="color:#00009f">extends</span><span class="token generics"> </span><span class="token generics class-name">DataTypeParent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> dataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">DisruptorProvider</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataTypeParent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> provider </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> providerManage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProvider</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        provider</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">DataTypeParent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">cast</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">close</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        providerManage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getProvider</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">shutdown</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>配置文件的加载，可看作是注册中心服务端初始化流程，用图描述如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/server-register-init-zh-f459729f048f19f89b7eaa023ae4b4e8.png" width="2464" height="807" class="img_ev3q"></p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="32-消费数据queueconsumer">3.2 消费数据QueueConsumer<a href="https://shenyu.apache.org/zh/blog/RegisterCenter-SourceCode-Analysis-Http-Register#32-%E6%B6%88%E8%B4%B9%E6%95%B0%E6%8D%AEqueueconsumer" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>在前面分析了客户端<code>disruptor</code>队列消费数据的过。服务端也是一样的逻辑，只是其中执行任务的执行者变了。</p>
<p><code>QueueConsumer</code>是一个消费者，它实现了<code>WorkHandler</code>接口，它的创建过程在<code>providerManage.startup()</code>逻辑中。<code>WorkHandler</code>接口是<code>disruptor</code>的数据消费接口，只有一个方法是<code>onEvent()</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">package</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">com</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token namespace" style="opacity:0.7">lmax</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">.</span><span class="token namespace" style="opacity:0.7">disruptor</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> </span><span class="token class-name">WorkHandler</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">T</span><span class="token plain"> event</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">throws</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>QueueConsumer</code>重写了<code>onEvent()</code>方法，主要逻辑是生成消费任务，然后在线程池中去执行。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * </span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * 队列消费者</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">QueueConsumer</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">WorkHandler</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataEvent</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token comment" style="color:#999988;font-style:italic">// 省略了其他逻辑</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">onEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">DataEvent</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> t</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">t </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 根据事件类型获取相应的线程池</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ThreadPoolExecutor</span><span class="token plain"> executor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">orderly</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">t</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 通过工厂创建队列消费任务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">QueueConsumerExecutor</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> queueConsumerExecutor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> factory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 保存数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            queueConsumerExecutor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">t</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// help gc</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            t</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 放在线程池中执行 消费任务</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            executor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">queueConsumerExecutor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>QueueConsumerExecutor</code>是在线程池中被执行的任务，它实现了<code>Runnable</code>接口，具体的实现类有两个：</p>
<ul>
<li class=""><code>RegisterClientConsumerExecutor</code>：客户端消费者执行器；</li>
<li class=""><code>RegisterServerConsumerExecutor</code>：服务端消费者执行器。</li>
</ul>
<p>顾名思义，一个负责处理客户端任务，一个负责处理服务端任务。</p>
<ul>
<li class=""><code>RegisterServerConsumerExecutor#run()</code></li>
</ul>
<p><code>RegisterServerConsumerExecutor</code>是服务端消费者执行器，它通过<code>QueueConsumerExecutor</code>间接实现了<code>Runnable</code>接口，并重写了<code>run()</code>方法。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">RegisterServerConsumerExecutor</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">QueueConsumerExecutor</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataTypeParent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//获取从disruptor队列中拿到的数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataTypeParent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> results </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">isValidData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">results</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//根据类型执行操作</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">selectExecutor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">results</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">executor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">results</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// 根据类型获取订阅者</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">ExecutorSubscriber</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataTypeParent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">selectExecutor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataTypeParent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> list</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">DataTypeParent</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> first </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> list</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findFirst</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> subscribers</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">first</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">orElseThrow</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">RuntimeException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"the data type is not found"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<ul>
<li class="">ExecutorSubscriber#executor()</li>
</ul>
<p>执行器订阅者分为两类，一个是处理元数据，一个是处理<code>URI</code>。在客户端和服务端分别有两个，所以一共是四个。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/executor-subscriber-86d5645d204ad1d05fe12dd30992c8d1.png" width="1732" height="403" class="img_ev3q"></p>
<ul>
<li class="">MetadataExecutorSubscriber#executor()</li>
</ul>
<p>如果是注册元数据，则通过<code>MetadataExecutorSubscriber#executor()</code>实现：根据类型获取注册<code>Service</code>，调用<code>register()</code>。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">MetadataExecutorSubscriber</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ExecutorTypeSubscriber</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">DataType</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">DataType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">META_DATA</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 元数据类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">executor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">MetaDataRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> metaDataRegisterDTOList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 遍历元数据列表</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        metaDataRegisterDTOList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">meta </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">shenyuClientRegisterService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">meta</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 根据类型获取注册Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuClientRegisterService </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// 对元数据进行注册，加锁确保顺序执行，防止并发错误</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">synchronized</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuClientRegisterService</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            shenyuClientRegisterService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">register</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">meta</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class="">URIRegisterExecutorSubscriber#executor()</li>
</ul>
<p>如果是注册元数据，则通过<code>URIRegisterExecutorSubscriber#executor()</code>实现：构建<code>URI</code>数据，根据注册类型查找<code>Service，</code>通过<code>registerURI</code>方法实现注册。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">URIRegisterExecutorSubscriber</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ExecutorTypeSubscriber</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">DataType</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">DataType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">URI</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// URI数据类型</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">executor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Collection</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> dataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 根据rpc调用类型聚集数据</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> groupByRpcType </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> dataList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">groupingBy</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">URIRegisterDTO</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">getRpcType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Map</span><span class="token class-name punctuation" style="color:#393A34">.</span><span class="token class-name">Entry</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> entry </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> groupByRpcType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">entrySet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> rpcType </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> entry</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 根据类型查找Service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">shenyuClientRegisterService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rpcType</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ifPresent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">service </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> list </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> entry</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token comment" style="color:#999988;font-style:italic">// 构建URI数据类型，通过registerURI方法实现注册</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token class-name">Map</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> listMap </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">list</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        listMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">service</span><span class="token operator" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">registerURI</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<ul>
<li class="">ShenyuClientRegisterService#register()</li>
</ul>
<p><code>ShenyuClientRegisterService</code>是注册方法接口，它有多个实现类：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/client-register-service-949e3110cb57db2f250dafdc41446eb4.png" width="4978" height="800" class="img_ev3q"></p>
<ul>
<li class=""><code>AbstractContextPathRegisterService</code>：抽象类，处理部分公共逻辑；</li>
<li class=""><code>AbstractShenyuClientRegisterServiceImpl</code>：：抽象类，处理部分公共逻辑；</li>
<li class=""><code>ShenyuClientRegisterDivideServiceImpl</code>：<code>divide</code>类，处理<code>http</code>注册类型；</li>
<li class=""><code>ShenyuClientRegisterDubboServiceImpl</code>：<code>dubbo</code>类，处理<code>dubbo</code>注册类型；</li>
<li class=""><code>ShenyuClientRegisterGrpcServiceImpl</code>：<code>gRPC</code>类，处理<code>gRPC</code>注册类型；</li>
<li class=""><code>ShenyuClientRegisterMotanServiceImpl</code>：<code>Motan</code>类，处理<code>Motan</code>注册类型；</li>
<li class=""><code>ShenyuClientRegisterSofaServiceImpl</code>：<code>Sofa</code>类，处理<code>Sofa</code>注册类型；</li>
<li class=""><code>ShenyuClientRegisterSpringCloudServiceImpl</code>：<code>SpringCloud</code>类，处理<code>SpringCloud</code>注册类型；</li>
<li class=""><code>ShenyuClientRegisterTarsServiceImpl</code>：<code>Tars</code>类，处理<code>Tars</code>注册类型；</li>
<li class=""><code>ShenyuClientRegisterWebSocketServiceImpl</code>：<code>Websocket</code>类，处理<code>Websocket</code>注册类型；</li>
</ul>
<p>从上面可以看出每种微服务都有对应的注册实现类，本文的源码分析是 以官方提供的 <a href="https://github.com/apache/incubator-shenyu/tree/master/shenyu-examples/shenyu-examples-http" target="_blank" rel="noopener noreferrer" class="">shenyu-examples-http</a> 为例，是属<code>http</code>注册类型，所以元数据和URI数据的注册实现类是 <code>ShenyuClientRegisterDivideServiceImpl</code>：</p>
<ul>
<li class="">register(): 注册元数据</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractShenyuClientRegisterServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">FallbackShenyuClientRegisterService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">register</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">MetaDataRegisterDTO</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 1.注册选择器信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> selectorHandler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">selectorHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> selectorId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginNameAdapter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcTypeAdapter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 2.注册规则信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> ruleHandler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ruleHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RuleDTO</span><span class="token plain"> ruleDTO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRpcDefaultRuleDTO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorId</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleHandler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ruleService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">registerDefault</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleDTO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 3.注册元数据信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">registerMetadata</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 4.注册contextPath</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> contextPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">contextPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">registerContextPath</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>整个注册逻辑可以分为4个步骤：</p>
<ul>
<li class="">1.注册选择器信息</li>
<li class="">2.注册规则信息</li>
<li class="">3.注册元数据信息</li>
<li class="">4.注册<code>contextPath</code></li>
</ul>
<p>在<code>admin</code>这一侧通过客户端的元数据信息需要构建选择器、规则、元数据和<code>ContextPath</code>。具体的注册过程和细节处理跟<code>rpc</code>类型有关。我们就不再继续向下追踪了，对于注册中心的逻辑分析，跟踪到这里就够了。</p>
<p>服务端元数据注册流程的源码分析完了，流程图描述如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/server-metadata-register-zh-1b1d9d30b0f3c8fedc59d9a82ab24896.png" width="2468" height="1071" class="img_ev3q"></p>
<ul>
<li class="">registerURI(): 注册<code>URI</code>数据</li>
</ul>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractShenyuClientRegisterServiceImpl</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">FallbackShenyuClientRegisterService</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">ShenyuClientRegisterService</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//......</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doRegisterURI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">uriList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 对应的选择器是否存在</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SelectorDO</span><span class="token plain"> selectorDO </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findByNameAndPluginName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginNameAdapter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcTypeAdapter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"doRegister Failed to execute,wait to retry."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">URIRegisterDTO</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> validUriList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> uriList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">filter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getPort</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNotBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dto</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHost</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Collectors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// 处理选择器中的handler信息</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> handler </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">validUriList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorDO</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">SelectorData</span><span class="token plain"> selectorData </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">buildByName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorName</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">PluginNameAdapter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">rpcTypeAdapter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">rpcType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 更新数据库中的记录</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectorService</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">updateSelective</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorDO</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// 发布事件</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            eventPublisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">publishEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DataChangedEvent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConfigGroupEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SELECTOR</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">DataEventTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UPDATE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">Collections</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">singletonList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectorData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ShenyuResultMessage</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SUCCESS</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>admin</code>拿到<code>URI</code>数据后，主要是更新选择器中的<code>handler</code>信息，然后写入到数据库，最后发布事件通知网关。通知网关的逻辑是由数据同步操作完成，这在之前的文章中已经分析过了，就不再赘述。</p>
<p>服务端<code>URI</code>注册流程的源码分析完成了，用图描述如下：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/server-uri-register-zh-4d956ca81d252f021f22e8a28d15bf2d.png" width="2261" height="1063" class="img_ev3q"></p>
<p>至此，服务端注册流程也就分析完了，主要通过对外提供的接口，接受客户端的注册信息，然后写入到<code>Disruptor</code>队列，再从中消费数据，根据接收到的元数据和<code>URI</code>数据更新<code>admin</code>的选择器、规则、元数据和选择器的<code>handler</code>。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-总结">4. 总结<a href="https://shenyu.apache.org/zh/blog/RegisterCenter-SourceCode-Analysis-Http-Register#4-%E6%80%BB%E7%BB%93" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>本文主要对<code>Apache ShenYu</code>网关中的<code>http注册</code>模块进行了源码分析。涉及到的主要知识点，归纳如下：</p>
<ul>
<li class="">注册中心是为了将客户端信息注册到<code>admin</code>，方便流量筛选；</li>
<li class=""><code>http</code>注册是将客户端元数据信息和<code>URI</code>信息注册到<code>admin</code>；</li>
<li class=""><code>http</code>服务的接入通过注解<code>@ShenyuSpringMvcClient</code>标识；</li>
<li class="">注册信息的构建主要通过<code>Spring</code>应用监听器<code>ApplicationListener</code>；</li>
<li class="">注册类型的加载通过<code>SPI</code>完成；</li>
<li class="">引入<code>Disruptor</code>队列是为了数据与操作解耦，以及数据缓冲。</li>
<li class="">注册中心的实现采用了面向接口编程，使用模板方法、单例、观察者等设计模式。</li>
</ul>]]></content>
        <author>
            <name>midnight2104</name>
            <uri>https://github.com/midnight2104</uri>
        </author>
        <category label="http" term="http"/>
        <category label="register center" term="register center"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[LoadBalancer SPI 代码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-LoadBalance-SPI</id>
        <link href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-LoadBalance-SPI"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[​        网关应用需要支持多种负载均衡的方案，包括随机选择、Hash、轮询等方式。Apache Shenyu网关中不仅实现了传统网关的这些均衡策略，还通过流量预热(warmup)等细节处理，对服务器节点的加入，做了更平滑的流量处理，获得了更好的整体稳定性。让我们来看看Shenyu是是如何设计和实现这部分功能的。]]></summary>
        <content type="html"><![CDATA[<p>​        网关应用需要支持多种负载均衡的方案，包括随机选择、Hash、轮询等方式。<code>Apache Shenyu</code>网关中不仅实现了传统网关的这些均衡策略，还通过流量预热(warmup)等细节处理，对服务器节点的加入，做了更平滑的流量处理，获得了更好的整体稳定性。让我们来看看Shenyu是是如何设计和实现这部分功能的。</p>
<blockquote>
<p>本文基于<code>shenyu-2.5.0</code>版本进行源码分析.</p>
</blockquote>
<p>[TOC]</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="loadbalancer-spi">LoadBalancer <code>SPI</code><a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-LoadBalance-SPI#loadbalancer-spi" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p><code>LoadBalancer</code> SPI 定义在<em><strong>shenyu-loadbalancer</strong></em>模组中，以下是这个核心接口的代码，这个接口很好的诠释了这样一个理念：负载均衡是在一系列服务器节点中选出最合适的节点，也就是选择策略。做流量转发、路由和负载均衡是<code>LoadBalance SPI</code>的基本功能</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@SPI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> </span><span class="token class-name">LoadBalancer</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * this is select one for upstream list.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param upstreamList upstream list</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param ip ip</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return upstream</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Upstream</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">select</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Upstream</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>接口中，upstreamList是可选路由的一组服务器节点，<code>Upstream</code> 是服务器节点的数据结构，它包括的重要元素有：协议、url 、权重、时间戳，warmup，健康状态等。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">Upstream</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * protocol.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> protocol</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * url.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * weight.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> weight</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * false close, true open.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> status</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * startup time.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> timestamp</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * warmup.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> warmup</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * healthy.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> healthy</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * lastHealthTimestamp.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> lastHealthTimestamp</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * lastUnhealthyTimestamp.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> lastUnhealthyTimestamp</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * group.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> group</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * version.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> version</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="design-of-loadbalance-module">Design of LoadBalance module`<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-LoadBalance-SPI#design-of-loadbalance-module" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>图1是<code>LoadBalancer</code>模组的类图：</p>
<p><img decoding="async" loading="lazy" alt="loadbalancer-class-diagram" src="https://shenyu.apache.org/zh/assets/images/loadBalancer-class-diagram-7fa8d2dd07f1210da7d25fa787b69d5f.png" width="3004" height="2774" class="img_ev3q"></p>
<p>从类图上可以看出<code>LoadBalance</code>的设计概要：</p>
<ol>
<li class="">
<p>抽象类<code>AbstractLoadBalancer</code>继承自<code>LoadBalancer</code> SPI接口，并提供选择的模板方法，及权重计算。</p>
</li>
<li class="">
<p>三个实做类继承<code>AbstractLoadBalancer</code>， 实现各自的逻辑处理。</p>
<ul>
<li class=""><code>RandomLoadBalancer</code> -加权随机选择 Weight Random</li>
<li class=""><code>HashLoadBalancer</code>  - 一致性Hash</li>
<li class=""><code>RoundRobinLoadBalancer</code> -加权轮询（Weight Round Robin per-packet)</li>
</ul>
</li>
<li class="">
<p>由工厂类<code>LoadBalancerFactory</code> 实现对外的静态调用方法。</p>
<p>另外根据<code>Apache Sheny SPI</code>规范，在<code>SHENYU_DIERECTORY</code>中的添加profile，配置<code>LoadBalance</code>的实现类，配置key=class形式，左边的operator要和<code>LoadBalanceEnum</code>中的定义一致。</p>
</li>
</ol>
<div class="language-properties codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-properties codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key attr-name" style="color:#00a4db">random</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">org.apache.shenyu.loadbalancer.spi.RandomLoadBalancer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">roundRobin</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">org.apache.shenyu.loadbalancer.spi.RoundRobinLoadBalancer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">hash</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">org.apache.shenyu.loadbalancer.spi.HashLoadBalancer</span><br></span></code></pre></div></div>
<p><code>LoadBalanceEnum</code>的定义如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">enum</span><span class="token plain"> </span><span class="token class-name">LoadBalanceEnum</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Hash load balance enum.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">HASH</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hash"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Random load balance enum.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">RANDOM</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"random"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Round robin load balance enum.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">ROUND_ROBIN</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"roundRobin"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> code</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> name</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> support</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="abstractloadbalancer">AbstractLoadBalancer<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-LoadBalance-SPI#abstractloadbalancer" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>这个抽象类实做了<code>LoadBalancer</code>接口, 定义了抽象方法<code>doSelect()</code>留给实作类处理，在模板方法<code>select()</code> 中先进行校验，之后调用由实作类实现的<code>doSelect()</code>方法。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractLoadBalancer</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">LoadBalancer</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Do select divide upstream.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param upstreamList the upstream list</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param ip           the ip</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return the divide upstream</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token class-name">Upstream</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doSelect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Upstream</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Upstream</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">select</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Upstream</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstreamList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstreamList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doSelect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstreamList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>权重的处理方法<code>getWeight()</code>的逻辑是：当有时间戳，并且当前时间与时间戳间隔在流量预热warmup时间内，权重计算的公式为：
$$ <!-- -->0<!-- -->
ww = min(1,uptime/(warmup/weight))
$$
从公式可以看出，最终的权值，与设置的weight成正比，时间间隔越接近warmup时间，权重就越大。也就是说等待的时间越长，被分派的权重越高。没有时间戳时等其他情况下，返回<code>Upstream</code>设置的<code>weight</code>值。</p>
<p>考虑流量预热(warmup)的核心思想是避免在添加新服务器和启动新JVM时网关性能不佳。</p>
<p>下面我们看一下三个实做类的实现。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="randomloadbalancer">RandomLoadBalancer<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-LoadBalance-SPI#randomloadbalancer" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>这里随机<code>LoadBalancer</code> 可以处理两种情况：</p>
<ol>
<li class="">没有权重：所有服务器都没有设定权重，或者权重都一样， 会随机选择一个。</li>
<li class="">有权重：服务器设定有不同的权重，会根据权重，进行随机选择。</li>
</ol>
<p>下面是有权重时的随机选择代码<code>random()</code>： 遍历全部服务器列表，当随机值小于某个服务器权重时，这个服务器被选中（这里提前计算了前一半服务器的权重和，如果随机值大于<code>halfLengthTotalWeight</code>，则遍历从<code>(weights.length + 1) / 2</code>开始，提高了小效率）。 若遍历后没有满足条件，就在全部服务器列表中随机选择一个返回。这里<code>getWeight(final Upstream upstream)</code> 方法是在<code>AbstractLoadBalancer</code> 中定义的，按公式计算权重。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Upstream</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doSelect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Upstream</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> length </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// every upstream has the same weight?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> sameWeight </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// the weight of every upstream</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">int</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> weights </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">length</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> firstUpstreamWeight </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getWeight</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstreamList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    weights</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> firstUpstreamWeight</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// init the totalWeight</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> totalWeight </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> firstUpstreamWeight</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> halfLengthTotalWeight </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> length</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> currentUpstreamWeight </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getWeight</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstreamList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">length </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            halfLengthTotalWeight </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> totalWeight</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        weights</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> currentUpstreamWeight</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        totalWeight </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> currentUpstreamWeight</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sameWeight </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> currentUpstreamWeight </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> firstUpstreamWeight</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Calculate whether the weight of ownership is the same.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            sameWeight </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">totalWeight </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">sameWeight</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">random</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">totalWeight</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> halfLengthTotalWeight</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> weights</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">random</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstreamList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Upstream</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">random</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> totalWeight</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> halfLengthTotalWeight</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> weights</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Upstream</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// If the weights are not the same and the weights are greater than 0, then random by the total number of weights.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> offset </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">RANDOM</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nextInt</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">totalWeight</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> index </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> end </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> weights</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">length</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">offset </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> halfLengthTotalWeight</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        index </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">weights</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">length </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        offset </span><span class="token operator" style="color:#393A34">-=</span><span class="token plain"> halfLengthTotalWeight</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        end </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">weights</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">length </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Determine which segment the random value falls on</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> index </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> end</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> index</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        offset </span><span class="token operator" style="color:#393A34">-=</span><span class="token plain"> weights</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">index</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">offset </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">index</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">random</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstreamList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>因此，当采用<code>RandomLoadBalancer</code>时，是按权重随机分派服务器的。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="hashloadbalancer">HashLoadBalancer<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-LoadBalance-SPI#hashloadbalancer" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p><code>Apache Shenyu</code>的<code>HashLoadBalancer</code> 中采用了一致性hash算法，使用有序hash环，将key与服务器节点的hash映射缓存起来。对于请求的ip地址，计算出其<code>hash</code>值， 在hash环上顺时针查找距离这个key的hash值最近的节点，将其作为要路由的节点。一致性hash解决了传统取余hash算法的可伸缩性差的问题。</p>
<p><code>HashLoadBalancer</code>中的采用的是加密的单向MD5散列函数，这个hash函数会hash后产生不可预期但确定性的()的结果，输出为32-bit的长整数。<code>hash</code>代码如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">hash</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// md5 byte</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">MessageDigest</span><span class="token plain"> md5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        md5 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">MessageDigest</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"MD5"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">NoSuchAlgorithmException</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ShenyuException</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"MD5 not supported"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> e</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    md5</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">reset</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> keyBytes</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    keyBytes </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> key</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBytes</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">StandardCharsets</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">UTF_8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    md5</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">update</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">keyBytes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">byte</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> digest </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> md5</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">digest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// hash code, Truncate to 32-bits</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> hashCode </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">long</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">digest</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0xFF</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">24</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">long</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">digest</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0xFF</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">16</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">long</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">digest</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0xFF</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">digest</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0xFF</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> hashCode </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain">xffffffffL</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>再看一下<code>HashLoadBalancer</code>的选择函数<code>doSelect()</code>的实现：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">VIRTUAL_NODE_NUM</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Upstream</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doSelect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Upstream</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConcurrentSkipListMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Long</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">Upstream</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> treeMap </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ConcurrentSkipListMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        upstreamList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstream </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">IntStream</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">range</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">VIRTUAL_NODE_NUM</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> addressHash </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">hash</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"SHENYU-"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> upstream</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"-HASH-"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            treeMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">addressHash</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> upstream</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> hash </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">hash</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">SortedMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Long</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">Upstream</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> lastRing </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> treeMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">tailMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">hash</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">lastRing</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> lastRing</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">lastRing</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">firstKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> treeMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">firstEntry</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>这个方法中，生成带虚拟服务器节点的hash环， 一个实际节点会生成5个虚拟节点，因此整个hash环的均匀性大大增加，降低数据倾斜的发生。</p>
<p>为了实现hash环的有序性及顺时针查找功能，代码中使用Java 的<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentSkipListMap.html" target="_blank" rel="noopener noreferrer" class="">ConcurrentSkipListMap</a> 来存储带虚拟节点的服务器节点及其hash值， 它既能保证线程安全，又能保证数据的有序性，支持高并发。 另外，<code>ConcurrentSkipListMap</code>提供了一个<code>tailMap(K fromKey)</code>方法，可从<code>map</code>中查找比<code>fromKey</code>大的值的集合，但并不需要遍历整个数据结构。</p>
<p>上述代码中，生成hash环之后，就是调用<code>ConcurrentSkipListMap</code>的<code>tailMap()</code>方法，找到大于等于请求的ip的hash值的子集，这个子集的第一个就是要路由的服务器节点。采用了合适的数据结构，这里的代码看上去是不是特别的简洁流畅？</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="roundrobinloadbalancer">RoundRobinLoadBalancer<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-LoadBalance-SPI#roundrobinloadbalancer" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>Round-robin轮询方法的原始定义是顺序循环将请求依次循环地连接到每个服务器。当某个服务器发生故障（例如：一分钟连接不上的服务器)，从候选队列中取出，不参与下一次的轮询，直到其恢复正常。在 <code>RoundRobinLoadBalancer</code>中实现的是组内加权轮询（<code>Weight Round Robin per-packet</code>)方法：</p>
<p>为了计算和存储每个服务器节点的轮询次数，在这个类中定义了一个静态内部类<code>WeigthRoundRobin</code>，我们先看一下它的主要代码（去掉了注释）：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">WeightedRoundRobin</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> weight</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">AtomicLong</span><span class="token plain"> current </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">AtomicLong</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> lastUpdate</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setWeight</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> weight</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">weight </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> weight</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        current</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">increaseCurrent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> current</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addAndGet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">weight</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sel</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> total</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        current</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addAndGet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> total</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setLastUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> lastUpdate</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">lastUpdate </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> lastUpdate</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>请重点关注这几个方法：</p>
<ul>
<li class="">
<p><code>setWeight(final int weight)</code> ，为对象设定权重，并将current重置为0.</p>
</li>
<li class="">
<p><code>increaseCurrent()</code> : 对<code>AtomicLong</code>类型的对象<code>current</code>，累加其权重值。</p>
</li>
<li class="">
<p><code>sel(final int total)</code>:   <code>current</code>减去传入的 <code>total</code>值。</p>
</li>
</ul>
<p>下面我们看一下带权重的轮询过程是如何实现的。
首先定义了一个<code>ConcurrentMap</code>类型对象<code>methodWeightMap</code> 两层对象来存储服务器列表与其各个明细节点的轮询资料。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConcurrentMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">ConcurrentMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">WeightedRoundRobin</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> methodWeightMap </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ConcurrentHashMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">16</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>这个map对象第一层的key为当前服务器列表的第一个节点的<code>upstreamUrl</code>,  第二个对象<code>ConcurrentMap&lt;String, WeightedRoundRobin&gt;</code>存储了组内各个服务器节点的轮询情况，内层Map的key为组内每个服务器的<code>upstreamUrl</code>。<code>Map</code>对象使用<code>JUC</code>的<code>ConcurrentHashMap</code>，不仅存取高效，而且线程安全，支持高并发。</p>
<p>内层map的每个节点对应的<code>WeighedRoundRobin</code>作为静态内部类能确保线程安全，并实现组内的加权轮询选择功能。下面是这个类的<code>doSelect()</code>方法的代码。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Upstream</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doSelect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Upstream</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">ConcurrentMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">WeightedRoundRobin</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> map </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> methodWeightMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">map</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        methodWeightMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">putIfAbsent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ConcurrentHashMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">16</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        map </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> methodWeightMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> totalWeight </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> maxCurrent </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Long</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">MIN_VALUE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> now </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">System</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">currentTimeMillis</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Upstream</span><span class="token plain"> selectedInvoker </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">WeightedRoundRobin</span><span class="token plain"> selectedWeightedRoundRobin </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Upstream</span><span class="token plain"> upstream </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> rKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> upstream</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getUrl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">WeightedRoundRobin</span><span class="token plain"> weightedRoundRobin </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> map</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> weight </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getWeight</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstream</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">weightedRoundRobin</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            weightedRoundRobin </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">WeightedRoundRobin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            weightedRoundRobin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setWeight</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">weight</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            map</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">putIfAbsent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> weightedRoundRobin</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">weight </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> weightedRoundRobin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getWeight</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// weight changed.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            weightedRoundRobin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setWeight</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">weight</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">long</span><span class="token plain"> cur </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> weightedRoundRobin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">increaseCurrent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        weightedRoundRobin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setLastUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">now</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cur </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> maxCurrent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            maxCurrent </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> cur</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectedInvoker </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> upstream</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            selectedWeightedRoundRobin </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> weightedRoundRobin</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        totalWeight </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> weight</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">//erase the section which handles the time-out upstreams. </span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectedInvoker </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectedWeightedRoundRobin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sel</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">totalWeight</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> selectedInvoker</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// should not happen here</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>举例，若服务器组<code>upstreamUrl</code> 分别为： LIST = [upstream-20, upstream-50, upstream-30]时，经过一轮执行后，建立的<code>methodWeightMap</code> 资料如下：</p>
<p><img decoding="async" loading="lazy" alt="methodWeightMap" src="https://shenyu.apache.org/zh/assets/images/methodWeightMap-90b4a77aedffd8cd88bc12b9551739ad.png" width="559" height="150" class="img_ev3q"></p>
<p>假设上述的LIST中，各个服务器节点的权重数组为: [20,50,30], 下图是内部类current 值变化和轮询选择过程：</p>
<p><img decoding="async" loading="lazy" alt="weighted-roundrobin-demo" src="https://shenyu.apache.org/zh/assets/images/weighted-roundrobin-demo-cec02fd422fb01ef73e882e0966a8cec.png" width="1025" height="442" class="img_ev3q"></p>
<p>每一轮，选择值current最大的服务器节点：</p>
<ul>
<li class="">Round1:<!-- -->
<ul>
<li class="">对当前服务器LIST做遍历，当服务器节点的weightedRoundRobin 为null时，current被置为各自的权重； 不为null时，累加各自的权重。</li>
<li class="">即：遍历后current 分别为 [20, 50,30] ， 会选择Stream-50, Stream-50对应的WeightRoundRobin静态类做 sel(-total)处理，current 更新为[20,-50, 30].</li>
</ul>
</li>
<li class="">Round 2  遍历后的current是[40,0,60],  会选择Stream-30， current分别更新为[40,0,-40].</li>
<li class="">Round 3  遍历后的current是[60,50,-10],  会选择Stream-20，current分别更新为[-40,50,-10].</li>
</ul>
<p>中间进行了容错处理， 当服务器的个数与map个数不一样，就对methodWeightMap 加锁做处理。 用先copy 后modify的方式， 把超时的服务器remove掉，即移除掉发生故障的服务器，并更新Map资料。如下是异常时的处理代码：</p>
<div class="language-Java language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">updateLock</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> map</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">size</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> updateLock</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">compareAndSet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// copy -&gt; modify -&gt; update reference.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">ConcurrentMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">,</span><span class="token generics"> </span><span class="token generics class-name">WeightedRoundRobin</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> newMap </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ConcurrentHashMap</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">map</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            newMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">entrySet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">removeIf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">item </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> now </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> item</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getValue</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLastUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> recyclePeriod</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            methodWeightMap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">put</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> newMap</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">finally</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            updateLock</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">set</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">nonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selectedInvoker</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        selectedWeightedRoundRobin</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">sel</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">totalWeight</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> selectedInvoker</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// should not happen here.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="loadbalancerfactory">LoadBalancerFactory<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-LoadBalance-SPI#loadbalancerfactory" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>在这个工厂类中，提供了调用<code>LoadBalancer</code>的静态方法, 其中<code>ExtensionLoader</code> 是<code>Apache Shenyu</code>的<code>SPI</code>执行入口。也就是说，LoadBalancer模组是可配置、可扩展的。这个静态方法中的<code>algorithm</code>变量是<code>LoadBalanceEnum</code>中定义<code>name</code>枚举类型。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Selector upstream.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * @param upstreamList the upstream list</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * @param algorithm    the loadBalance algorithm</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * @param ip           the ip</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * @return the upstream</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">Upstream</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">selector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Upstream</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> upstreamList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> algorithm</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> ip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">LoadBalancer</span><span class="token plain"> loadBalance </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ExtensionLoader</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getExtensionLoader</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">LoadBalancer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getJoin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">algorithm</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> loadBalance</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">select</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstreamList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="using-of-loadbalancer-module">Using of LoadBalancer module<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-LoadBalance-SPI#using-of-loadbalancer-module" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>上面说明了<code>LoadBalancer</code> SPI接口及三个实作类。下面看一下<code>LoadBalancer</code>在<code>Apache Shenyu</code>中是如何被调用的。<code>DividePlugin</code>是路由选择插件，所有的Http请求都由该插件进行负载均衡处理。当请求头rpcType = http, 且开启该插件时，它将根据请求参数匹配规则，最终交由下游插件进行响应式代理调用。</p>
<p>在<code>DividePlugin</code>的<code>doExecute</code>方法中，先对要转发的请求的Header大小、content长度等做校验，</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doExecute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>接口方法的第二个参数是<code>ShenyuPluginChain</code> 类型，代表<code>plugin</code>的调用链，具体可参见<code>Apache Sheyu</code> 的<code>plugin</code>的调用机制。第三个<code>SelectorData</code>类型的参数是选择器， 第四个是<code>RuldData</code>类型，代表规则。分别请查看对应的代码。</p>
<p>下面给出了<code>doExecute</code>()方法中，有关<code>LoadBalancer</code>调用的代码片段：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">//取到要路由的服务器节点列表。</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Upstream</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> upstreamList </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">UpstreamCacheManager</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">findUpstreamListBySelectorId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//取到请求的ip</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> ip </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">requireNonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRemoteAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHostAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//调用Util方法，执行LoadBalancer处理</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Upstream</span><span class="token plain"> upstream </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">LoadBalancerFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">selector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">upstreamList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getLoadBalance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ip</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>这里<code>UpstreamCacheManager</code> 是缓存的要路由的服务器节点 ， <code>ruleHandle.getLoadBalance()</code>取到的是<code>LoadBalanceEnum</code>定义的枚举name, 如<code>random, hash, roundRobin</code>等.</p>
<p>经过封装，调用负载均衡功能非常的方便。  未来增加新的<code>LoadBalancer</code>类，这些调用的<code>Plugin</code>代码完全不需要变更。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-LoadBalance-SPI#summary" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>经过上面的代码解读，从设计角度总结<code>LoadBalancer</code> 模组具有如下的特点：</p>
<ol>
<li class="">
<p>可扩展性：面向接口的设计，及基于Apache Shenyu SPI的实现，使得系统具有良好的可扩展性。可以方便的扩展为其他的动态的负载均衡算法，如最少连接方式(least connection)、最快模式( fastest)。并支持集群处理，具有良好的可扩展性。</p>
</li>
<li class="">
<p>可伸缩性：采用的一致性hash、权重随机和权重轮询算法，都可以无缝支持集群扩容或缩容。</p>
</li>
<li class="">
<p>流量预热等更细致的设计，能带来整体上更为平滑的负载均衡。</p>
</li>
</ol>]]></content>
        <author>
            <name>Huihui Yin</name>
            <uri>https://github.com/changanjennifer/</uri>
        </author>
        <category label="load balance" term="load balance"/>
        <category label="SPI" term="SPI"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[MatchStrategy--基于SPI的代码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-MatchStrategy-SPI</id>
        <link href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-MatchStrategy-SPI"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[Apache Shenyu 网关的各个Plugin（包括Dubbo, gRPC,Spring-cloud等) 中，routing参数均设计为可以接受多个条件的组合。 为了实现这样的目的，遵循其SPI的机制进行将参数及行为抽象为如下三部分，这些SPI 在shenyu-plugin-base模组中实现]]></summary>
        <content type="html"><![CDATA[<p><code>Apache Shenyu</code> 网关的各个<code>Plugin</code>（包括<code>Dubbo</code>, <code>gRPC</code>,<code>Spring-cloud</code>等) 中，<code>routing</code>参数均设计为可以接受多个条件的组合。 为了实现这样的目的，遵循其<code>SPI</code>的机制进行将参数及行为抽象为如下三部分，这些<code>SPI</code> 在<em><strong>shenyu-plugin-base</strong></em>模组中实现</p>
<ul>
<li class=""><code>ParameterData</code>-参数资料</li>
<li class=""><code>PredictJudge</code>-断言</li>
<li class=""><code>MatchStrategy</code>-匹配策略</li>
</ul>
<p>相对而言，匹配策略是需要扩展点最少的部分。想象一下，对多个条件的组合判断，最常见的几种规则是：全部都满足、至少满足一个条件、至少满足第一个，或者大部分满足等等。 并且要做到对各种<code>plugin</code>的不同类型的参数，如<code>IP</code>, <code>header</code>, <code>uri</code>等。针对这些需求，如何将<code>MatchStrategy</code>设计得简单易用且容易扩展？</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="matchstrategy">MatchStrategy<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-MatchStrategy-SPI#matchstrategy" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p><code>MatchStrategy</code>的实现代码在<em><strong>shenyu-plugin-base</strong></em>模组中，基于<code>Apache Shenyu</code>的<code>SPI</code>创建机制， 设计上结合了工厂模式和策略模式，整体<code>MatchStrategy</code>的设计类图如下下：</p>
<p><img decoding="async" loading="lazy" alt="MatchStrategy-class-diagram" src="https://shenyu.apache.org/zh/assets/images/MatchStrategy-class-diagram-ac006eef5089ce92a972e039b431100b.PNG" width="886" height="516" class="img_ev3q"></p>
<p>以接口<code>MatchStrategy</code>为基础，设计实现类，并由抽象类<code>AbstractMatchStrategy</code>实现公共方法，由工厂类<code>MatchStrategyFactory</code>提供创建和外部调用功能。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="matchstrategy-interface">MatchStrategy Interface<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-MatchStrategy-SPI#matchstrategy-interface" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>首先来看<code>MatchStrategy</code> <code>SPI</code>接口的定义：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@SPI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> </span><span class="token class-name">MatchStrategy</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">match</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConditionData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> conditionDataList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>@<code>SPI</code> <code>annotation</code>代表这是一个<code>SPI</code>接口。<code>ServerWebExchange</code> 是 <code>org.springframework.web.server.ServerWebExchange</code> ,代表<code>HTTP</code>的 <code>request-response</code>  的交互内容。<code>ConditionData</code>的代码如下，更多说明可以参考<code>PredicateJudge</code><a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI/" target="_blank" rel="noopener noreferrer" class="">代码分析</a>中的说明，</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">ConditionData</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> paramType</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> operator</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> paramName</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> paramValue</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="abstractmatchstrategy">AbstractMatchStrategy<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-MatchStrategy-SPI#abstractmatchstrategy" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>在抽象类<code>AbstractMatchStrategy</code>中，定义<code>MatchStrategy</code>的公共方法， 用<code>buildRealData</code>方法中，用<code>ParameterData</code>工厂类<code>ParameterDataFactory</code>，将多种参数如  <code>Ip</code>, <code>Cookie</code>, <code>Header</code>,<code>uri</code>等资料都以统一的接口方法来呈现。这些参数格式及规则的修改，不会影响到对参数规则匹配<code>MatchStrategy</code>的调用。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AbstractMatchStrategy</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRealData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConditionData</span><span class="token plain"> condition</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ParameterDataFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">builderData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">condition</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getParamType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> condition</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getParamName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="实现类及profile">实现类及Profile<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-MatchStrategy-SPI#%E5%AE%9E%E7%8E%B0%E7%B1%BB%E5%8F%8Aprofile" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>基于上述接口定义, <em><strong>shenyu-plugin-base</strong></em> 模组提供了两个<code>MatchStrategy</code>实现类</p>
<ul>
<li class="">
<p><code>AndMatchStrategy</code>-多个条件 AND</p>
</li>
<li class="">
<p><code>OrMatchStrategy</code>- 多个条件 OR</p>
<p>并在<code>SHENYU_DIRECTORY</code>目录下的配置文件中，对实作类做了配置。在系统启动时会由顶层<code>SPI</code>以<code>key-value</code>形式加载并<code>cache</code>起来。</p>
</li>
</ul>
<div class="language-properties codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-properties codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key attr-name" style="color:#00a4db">and</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">org.apache.shenyu.plugin.base.condition.strategy.AndMatchStrategy</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">or</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">org.apache.shenyu.plugin.base.condition.strategy.OrMatchStrategy</span><br></span></code></pre></div></div>
<p>两个实现类<code>AndMatchStrategy</code> 继承<code>AbstractMatchStrategy</code> 并实做了<code>MatchStrategy</code>。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="andmatchstrategy---与的关系">AndMatchStrategy-  “与”的关系<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-MatchStrategy-SPI#andmatchstrategy---%E4%B8%8E%E7%9A%84%E5%85%B3%E7%B3%BB" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>由于<code>PredicateJudge</code>封装了条件判断的多样性，<code>ConditionData</code>和<code>ParameData</code>封装了多种参数。那么对于多个条件的匹配来说，采用<code>Stream</code>流处理及<code>lamda</code>表达式，非常简洁高效达成了：全部条件都满足，即"AND"的逻辑。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@Join</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AndMatchStrategy</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">AbstractMatchStrategy</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">MatchStrategy</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">match</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConditionData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> conditionDataList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> conditionDataList</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">stream</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">allMatch</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">condition </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">PredicateJudgeFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">judge</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">condition</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">buildRealData</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">condition</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>OrMatchStrategy</code>是同样的实现方式，实现: 至少满足一个条件"OR"的规则，在此不做赘述。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="matchstrategyfactory">MatchStrategyFactory<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-MatchStrategy-SPI#matchstrategyfactory" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>这是<code>MatchStrategy</code>的工厂类，实现了两个方法，一个是<code>newInstance()</code>方法根据策略代码和名称，返回由<code>SPI</code> <code>ExtensionLoader</code>按key来加载对应的<code>MatchStrategy</code>实现类。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">MatchStrategy</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">newInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Integer</span><span class="token plain"> strategy</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> matchMode </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">MatchModeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMatchModeByCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">strategy</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ExtensionLoader</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getExtensionLoader</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">MatchStrategy</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getJoin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">matchMode</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>在<code>MatchModeEnum</code> 中定义了match策略的code和name。 调用时由策略名称，如"and","or"，根据启动时SPI加载的key-value资料，找到对应的实现类：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">AND</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"and"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">OR</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"or"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>另一个是<code>match()</code>方法，调用实作类的<code>match</code>方法。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">match</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">Integer</span><span class="token plain"> strategy</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">ConditionData</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> conditionDataList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">newInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">strategy</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">match</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">conditionDataList</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="调用方式">调用方式<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-MatchStrategy-SPI#%E8%B0%83%E7%94%A8%E6%96%B9%E5%BC%8F" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>在<code>shenyu-plugin</code>模组的各个<code>plugin</code>的基类<code>AbstractShenyuPlugin</code> 中，定义了两个选择的方法：<code>filterSelector</code> 和<code>filterRule</code> 它们都调用了<code>MatchStrategyFactory</code> 方法，下面是<code>AbstractShenyuPlugin</code>中<code>filterSelector</code>方法的代码：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">filterSelector</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token class-name">SelectorTypeEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">CUSTOM_FLOW</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CollectionUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isEmpty</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getConditionList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">MatchStrategyFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">match</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMatchMode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getConditionList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>这段代码中，先检测参数匹配条件<code>SelectorData</code>是否为空，之后调用<code>MatchStrategyFactory</code>的<code>match</code>方法，工厂方法将调用对应的实作类的<code>match</code>方法。同理，如下是<code>AbstractShenyuPlugin</code>中 <code>filterRule</code> 方法</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">filterRule</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token plain"> ruleData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getEnabled</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token class-name">MatchStrategyFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">match</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMatchMode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ruleData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getConditionDataList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>也同样是调用<code>MatchStrategyFactory</code>的<code>match</code>方法，看上去是不是特别的简洁甚至是简单？ 在<code>PredicteJudge</code>的<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI/" target="_blank" rel="noopener noreferrer" class="">代码分析</a>文中，对<code>shenyu-plugin</code>如何做参数调用方面做了更进一步的描述。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-MatchStrategy-SPI#summary" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>由于应用了<code>Apache shenyu</code>的<code>SPI</code>框架，使得整体上具有松耦合、易于扩展的特点。在多个参数规则策略方面，<code>MatchStrategy</code>提供了良好的设计，虽然目前只提供了两个AND 和OR的实现类，但未来可以很轻松地扩展为更多<code>MatchStrategy</code>规则，例如 <code>firstOf</code>：即必须满足第一个条件，或<code>mostOf</code>-满足大部分条件等更多复杂策略，而其他调用部分的代码完全不受影响。</p>
<p>有兴趣的读者可以去阅读<code>Shenyu plugin</code>的源码了解更多内容。</p>]]></content>
        <author>
            <name>Huihui Yin</name>
        </author>
        <category label="SPI" term="SPI"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[PredicateJudge-- 基于SPI的设计实现分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI</id>
        <link href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[灵活的插件和规则定义，是Shenyu网关的一大特色。它以插件形式支持多种网络协议和多种流行的微服务框架，如Dubbo, gRPC和 Spring-Cloud 等。 为了实现对各种协议及插件的配置规则的解析，网关在规则策略解析方面，采用了优雅的SPI(Service Provider Interface)实现，当添加新的插件时，规则解析部分可以沿用现有实现或采用SPI机制快速实现，具有良好的可扩展性。]]></summary>
        <content type="html"><![CDATA[<p>灵活的插件和规则定义，是<a href="http://shenyu.apache.org/" target="_blank" rel="noopener noreferrer" class="">Shenyu网关</a>的一大特色。它以插件形式支持多种网络协议和多种流行的微服务框架，如Dubbo, gRPC和 Spring-Cloud 等。 为了实现对各种协议及插件的配置规则的解析，网关在规则策略解析方面，采用了优雅的<code>SPI</code>(Service Provider Interface)实现，当添加新的插件时，规则解析部分可以沿用现有实现或采用<code>SPI</code>机制快速实现，具有良好的可扩展性。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="spi-的顶层设计"><code>SPI</code> 的顶层设计<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI#spi-%E7%9A%84%E9%A1%B6%E5%B1%82%E8%AE%BE%E8%AE%A1" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>Shenyu的<code>SPI</code>采用接口+ 工厂模式+配置文件的方式，来实现模组的动态加载。在其<em><strong>shen-<code>SPI</code></strong></em>-模组，做了<code>SPI</code>的顶层设计。定义了@ Join ，@<code>SPI</code> 两个annotation。 其中@Join  代表此类会加入扩展机制，相当于是做申请注册。 @<code>SPI</code> 标明当前类为<code>SPI</code>功能扩展类。</p>
<p>Fig 1 classes in the <em><strong>shenyu-spi</strong></em></p>
<p><img decoding="async" loading="lazy" alt="toplevel-SPI" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASkAAACeCAYAAABuIfz7AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAABX0SURBVHhe7Z39kxXVmcf5l1L70/y2STbRaLTKJEQoeTFBBtYkG8iS2ggoiChCcBCFlEQriElF0RWoiplaYGCDMRiRXQEtglNmABdKN1izI+iaicBJP6fP6T4vz+nue29f7pnu78c65b3d5637nudzTx/udM8SAAAQMZAUACBqICkAQNRAUgCAqBmYpM5f/FCcfu+slcbPvi8uf/KpygEAAAOU1KvHTog9+3/npX0HjkhZge4ZHZ4lZg2Pqnc3hkG0GRvyHAyNiHH1HtQDK6kXXnhB7N69W0xMTKgtNpOTk2LPnj0yH6VuCElKpzN/Pqdygk6BpAbBuBgZgqT6ASspElRIVK6g+iWpKonqAD6QFGgSrKRITJyoXEG98cYbMnUDJNU/ICnQJIJrUq6oTp065Qnq+vXrMnVD3yU1PiKGZiWBYyQ3hmRgJdPz0ZGhNI85VR8dtsoOjYym0/nCQFRT/qzcsDBz6/bG3b55dRbXkzIqhs06jL5rYYzr4wrV4faj9FLFbtPsdj1tquMuqCc7h+q9Rm9/V/VxaMTOESqXU3JsVLbkcytvA3RD4cK5KSozaUH1giup3xx+TZy78IH4+Mon8v+vHP6DtZ9LQUkpwVhjSA0wc/DKQcUMNh0g3kBl8pqMjwyLvHp/jSKrwxzIeuAb9ZbVo4/PCsSknsSjEt1Ovl8FoFfHUHE7Fn7wj474x9Zbm+o9V48+P14dRJonzeL3k5D96/HYrPLM51bcBuiWQkkRrqjqEBThSuri/15Se1IufvgXaz+XeEnxg5RI5eN8K3vf9qHyKoAKJOUhA6qsPb9fHlY95f3ggsVuI63Dq0IGnisAhQrKULP1tKmOrUI91udjnZ8uJFXl2LL6c9jxBEnVTqmkCC2qugRFuJL6/OpVtSfl88+vWvu5xEqqaMA538LsoAqWL5cDkQ5oM1UYxMzsIFhPSUARsqyTwQooVYddf574utXxUx7mGOppkz/Hrgzk+6wPrrS6mUlVOLYKn1txG6BbKkmqH7iSmpz6WO1Joffmfi7FJak0OMxgStvL31cb7CX11CipojqCmLIxjqWeNqtJKq1LnS/ztaQbSSmKjq30c6vYBuiYaCQ19oc3xZVP/1/uo//Te3M/l1hJBQYp4Q52flCFyit5hKLMGbAE254ZbAqrH6X1hI9PI+srDPTyOkqR/cylU0+bFSWl8lFdcp/1GfJ18J91AO7Yyj435j2oh2gkpRMtoHPbucRLSg9q51vbGXhEaFClg9IWRbotSVkFjrTc+rNv5Xxw+3UkuOUq1BM6Pv1etmPt1GVK6qC2sg3O8SX7hu0TkpR3ZhE9t1lVUgnU/lByzEl+J3vaFzO/Oqf5Z93FsZn5CVWnvclsA9RFdJLqJIUkJdEDM0u2dIiiQZUNTJWGR90A8gNKB6FMVK/sQx4sur3sJw9Z3SqDoqweiXt8RiWyHadSLtCtdihZ58I/PvucMBLvQ5sEV0/SYioabzuh6tFtJPXpc5+21cWxVfjc7DZAXTRXUrXDB1AnYBDXSe+fR1XwuQ2WgUlq6vIn4tLk//WUqI4bhrrs6iUmMNhrRH4e/uy4H+BzGywDk1TM0OWFvcCrLi16HKgY7PUhz+UNmEUR+NwGCyQVQA5MY/2hjoDAYO+dbE3rBp5HfG6DBZICAEQNJAUAiBpICgAQNZAUACBqICkAQNRAUgCAqIGkAABRA0kBAKKmdZL627VpcXbqjDh64aA4dH6fTPSattE+AEBctEZS15P/3rn0pnj+9Hax6+0RNtE+ykN5AQBx0ApJTV/9q9g/8RIrJi5RXirTVCbunyWemjsiJtV7AGKm8ZKiWVEngtKJyhTNqCZ3Dokd/zDLS2NHVIZoGRfH5/ZPUjP3vIBYabyk6PKNk1CVRGVDUDD2FuijYuwLzQteeV6+MCz4B/TXQTPPGwjTaEnRQnhoDWrJ2rvEwhXflIlec3mobGgxHZLigaRA3TRaUmen3mXlQ2nL/gfEvGV3yESvuTyUqA6OIknRPv8SJw2up+4fzfab6aWdxo1Azo6Il5K8ep/djrpcc+rxxZC2p/ebfWHXpJw23TJV25XnpVBSaT2h8il233VfOz1vlFyZ6WOfUHXR65OBNTqs3cVBoyX1+sUxVjw63bt+gUzcPp2oDg4ZjAUD2B7geYDnBGYER4aTwB0Sx8+q994aUh7keYDmAjTfmwE8sTPvqxd8SZteQKuAz+uo0m65pCZ3DhccW4Lqiyuf41nfwuet/BjSY6d81mfhnXMi0A644TRaUofO7WPFo1MVSVEdHNy3uh2cuSj4wOWCIA1aLzBksOkgYgI7wWpDBWcowGxJ5f10sftdoV31vvi8OEhBOG1YMnfhzlvVY1DH7vUnbdcqb/ULDBJIqgdJuQHroWThf0sTTLCp/G6Q65Tm5QOZEwqV4fpoSapIaNYMo0q7/nsOPZvRKctfIteU8HkrPwZX0Dn258lICwwMXO6VSKrbyz1Jl5IqDtJqspCo+lxZDU5S6TFb+80ZS6Xj74+k0jpUPvM1GDitXTh//MCabOGcXnN5KHWzcJ6SfxvzeZlgU9uKv8E7kJQmCVQSlW7LDtRwm3adNUjKEQZh569y/J2dN7c/QUmVfl5gUDRaUoP8CYIdDFyA84FF9ZpCkdA3e1a2giyS/GNmvSWzCbZNR2x1ScqqU82A3PJcX/L3HZw37xiKJJVA52lu0lZynFY9YKA0WlJEP3/MSQHgJgpiGQju5YIOSDPIVRBRMoPOrdsOqmqyoD5k5Z2+sIFq9IUrU4ukEsxjk30gMbj53b44bYbOW/kxlEhKCbCo/+DG03hJ9evPYkAT4UUMBkvjJUXgD4xBJbBgHiWtkBRBsyK6fAutUVGifZQHM6h2Ii8FMYuKjtZISkML4bjpHTDR62ThtSowSFonKQDAzAKSAgBEDSQFAIgaSAoAEDWQFAAgaiApAEDUQFIAgKhpvKQuf/KpOHz0uNj18m/Fq8feUlsBADOFRkvqg798JJ7bMyp+/vw+mXa/clBMX7su/jQ1LQ5cuCL2nr8sE72mbbQPABAXjZUUzaBMQVHad/SE2HZ6Umx++yM20b5jlz7DH8UAEBGNlRRd4pmCembvfvHYiQ9ZObnpxYmPxWdXr6mamkfx7UpmMriLQRNprKR2vZzPop7Zs19s+a//EVv++OeORFU0ozLvi2Sm+G+WpgK5T5Iqu59Uf4GkmkhjJfXqsRNi9ytj8hKPxESC+vmLvxFPHvpvVkpcoku/EDIYewp07ja4Mx9ICtRNoxfOaSFcr0GRqEhQO/79P+Tr5b/eLxasf0LMXrFWfGfTDrHm8DuepKhsaDEdkuKBpEDdNFpSZ6amPfE89tYHYtFDj4ub5i8Wdz/6M7HkyV+KOSsfEbct/ZHYyFwKUh0cRZKiff6ln7o1bRJAer+ZrNvgqlsN6312O3kgmvX4Ykjb0/vNvrBrUk6bbpmq7crzUiap0raItL1QOxLvNsMjvKQKz2d+PsynGnf/5QPqptGSOnjxiiedZb8aFTcvXCLWH33P2r4pkZf5Xieqg0MGY8FgtkXAfcMHZlLynt/m3SFVWacuCqZcbLkAzfem+GJ5gnG1tqieak86Nuuh46Jt1nkuPZ+BciAaGi2pvecue9KZ/+AWOYNyt4cS1cFhziZ0soMzFwUfuJyk0gDyxCWDWAcaE7AJVhsq6L16FLakfKFp7H5XaJd5b1O1LQYpG70/VI/qYyabKudTnY+itsFAaaekNmz3todSkaTcgPVQsuCeWsJKSuV35adTmtcNxBROKFSG66MlqSKhWbOQKu2WyKZyWyl6hqNTVm+wHqePlc6nK20QG+283FswLNb9ftzavmbspPVep24v9yQqSDqVFBvEGdVkITGC1Oxr/JJKz41VjzmTCtbDS6r4fEJSsdO6hfPNpy6JOas2iJvm3SNoRjW8dZf4xvLV4ub5i8WGY+97+btZOE9JAya73PPyMpIKXsaYdCApTRLg4ZlDuE27zhokVbUtZlZl1xuqJ92e97HK+YSkYqfRkjJ/gmClRFQ0o5q3dkTMue9hsXjrs+Kh1+yZFaVefoJgD3wuwPkAonpNoUhoRpCVrSCLJH+UTzBOqNSW+17NiMx65TE4IqNtVM7sI9uedT4hqdhptKQI+kGmK5+qqezHnDT43UQBwgVQFmhmkKtgpGTKyq3bDqBqstABK8szwewFpdEXrkwnkjLryeoLHLfc57Vl1yP7mpRx5WceI6WxI+E+mvncY4ek4qbxkqJ5EP2JCyeholT2ZzEAgBtD4yVF0B8LdyKqpv+BMQAziVZIiqBZEV2+sWtUKtE+3KoFgLhojaQ0tBCOm94BMHNonaQAADMLSAoAEDWQFAAgaiApAEDUQFIAgKiBpAAAUQNJAQCiBpICAERN6yT1t2vT4uzUGXH0wkFx6Pw+meg1baN9AIC4aI2krif/vXPpTfH86e1i19sjbKJ9lIfyAgDioBWSmr76V7F/4iVWTFyivFSmn+D2IABUo/GSollRJ4LSicqUz6j4+xeVo8pBUgCU0nhJ0eWbKZ9nT42INc8tEwtWfEvcftc/iVvnfEl8e+nXxfKRe8TTxx618lLZYrqVFACgKo2WFC2Em2tQO08+JhatvFPMufc28dDuFeIXb22W27f9bp249+GFYvbiW8VTr2/I8lPZ4sV0SAqAftNoSZ2dejcTDqVVz3xfzF5yq3jmzY3JrGmjWL3zX8SKbUvEfTvuFTuOPiLuWT1X/GDj3VYZqiNMQFLqVsHmLWute2wn2GtSeT3WbXML7hUOQFtotKRevzhmCeeuZXdIUe1441HxzUVfE8s2f1ds2PMTccudXxI/fWWlfE3bzTJURxhGUu5DBAglLfM+5pykqFyex33yCQDtpNGSOnRunyWc2+d/VWz+7Sqx5rkfijv/+Ta5jS4Bb/n2F8XI/gfE4wfWSGGZZaiOMK6kwo9Qch9YwM6knIV0twwAbaRdkpr3FSmjnySXdwtXfEtu2/bqevG12f8onvjPdWLd8//qzaQ6kpSaMbmXdhL5tJP8qSihyz0TSAqAll3uzf3e7eL+XT+UM6avz/2yvPRbtGqOuH3BV8XSdfPE7OFbxY+fXGKVqXK5l82cICkAaqdVC+ckoHnL75A/Q6AZ1Y+3LxWPvPxvciF9ZSIs+hc/2meWKV44Ty/vcin1eLkHSQHg0WhJuT9BePr4JrkWtfj+uWLr4QflNlqTeiJ5TQvnOp9OZT9B4CRC27yFc2YxHZICoBqNlhTh/pjz6WTWtOyxRfIHnLQWdcudX5SXgat/8QMrHyX+x5ypUNKfCPhP3pUoKenE5YOkAKhG4yXV3z+LAQD0m8ZLiojxD4wBANVohaQImhXR5Zu5RuUm2kd5MIMCIB5aIykNLYTjpncAzBxaJykAwMwCkgIARA0kBQCIGkgKABA1kBQAIGogKQBA1EBSAICogaQAAFEDSQEAoqZ1ksIvzgGYWbRGUvjbPQBmJq2QFO6CAMDMpfGSollRJ4LSicqUzqjcm9tlN7FL0XfpLMpj3/wOAODSeEnR5Zspn7oes87eNTORlnl/c5nHEpC6A6exDZICoJhGS4oWws01qPoesx5+4IKJL6kE54kykBQAxTRaUv17zHq1pwuzknKeMANJAVBMoyXVz8esk1zkGlOBqMIzqdDz9wAALo2WVL8fs04SyhbEGVn5kvJnYJAUAMW0S1K1P2Y9JZtVOY+uMiWmk7uOBUkBUEyrLvfqf8y6ifqXO+Nf/Pg1KRtICoBiWrVwXv9j1h2ODENSANRMoyXl/gShvses09qS+1Ri/ynEkBQAvdNoSRHujzl7f8y6Jl0EL1pvgqQA6J3GS6qvfxYDAOg7jZcUgT8wBmDm0gpJETQross3c43KTbSP8mAGBUA8tEZSGloIx03vAJg5tE5SAICZBSQFAIgaSAoAEDWQFAAgaiApAEDUQFIAgKiBpAAAUQNJAQCipnWSmr52XfxpalocuHBF7D1/WSZ6TdtoHwAgLlojKdLPsUufiW2nJ8Xmtz9iE+2jPFAVAPHQCkl9dvWaeHHiY1ZMXKK8VOZG0aTbteDWM6BuGi8pmhV1IiidqEzpjKrkCcbV8B8Yyt0bnZJ+DFa8+MdSJzP3vIBeaLyk6PKNk1CVRGVDyBvalTzBuFuq3CyvGPvZfk2BPee10szzNtNptKRoITy0BrX81/vFgvVPiNkr1orvbNoh1hx+x8tDZakOn3Qw1yEkDkiKB5JqJ42W1JmpaU88m09dEnc98FNx0/zF4u5HfyaWPPlLMWflI+K2pT8SG0986OWnOnzSwVz2BONsfUY9Wl1fnrjl3HWcIknRPv8SJ++P3m8mS6ZuX6x28vu0m/X4Ykjb0/vNvrBrUk6bbpmq7crzUiiptJ5Q+RS777qvnZ43Sq7M9LFPqLro9cnAGh3W7qrTaEkdvHjFk86yX42KmxcuEeuPvmdt3/TWB9Z7nagODhpkciAWiCrLYw5GNdjNcu6AlcFYMIDt/HmA5wRmBPJpNuYDJNw1pDzI8wB1hZy+NwN4YmfeVy/41Lqd1Rd1DvI6qrRbLqnJncMFx5ag+uLK53jWt/B5Kz8G4/M2PwvvnBOBdgBLoyW199xlTzrzH9wiZ1Du9lCiOkJY3/qWJFJkwDJB5QYbJyldb1a/VU8uCj5wuSBIg9YLDBlsOoiYwE6w2lDBGQow+1jyfrrY/a7QrnpffF4cpCCcNpjPKYc7b1WPIfR5p+1a5a1+gTLaKakN273toVQkKU32Dep8Y7ryyXC+XTlJseVMlCz8b2mCCTaV3w1yndK8fCBzQqEyXB+tYykSmnUOqrTrv+fQn4VOWf4SuaaEz1v5MYQ/b/vzZKQFCmnn5d6CYbHu9+PW9jVjJ633OoUu93xUoBlBFKOkioO0miwkqj5XVoOTVHrM1n7Zhnpf6fj7I6m0DpXPfA0q0cqF8zmrNoib5t0jaEY1vHWX+Mby1eLm+YvFhmPve/n5hfMAZlAkyEHLBJU7mDuXVP5tzOdlgk1tK/4G70BSmuSYSVS6LftYwm3addYgKUcYhJ2/yvF3dt7c/gQlVfp5gSIaLangTxASUdGMat7aETHnvofF4q3Piodes2dWlIp/guB+G/qBRoNWzjTM4HOCmuhUUnZ+LsD5wKJ63bblN3tWtoIskvxjZr0lswm2Te8c1CMpq041A3LLc33J33dw3ip8jhZ0nuYmbSXHadUDSmm0pIh+/ZhTD2gaqDq5g1sPWv1P0jq5gzQU2G6iIJZ5XUHqgDSDXAURJbNfbt12UFWTBfUhK+/0hQ1Uoy9cmVoklWAem+wDicHN7/bFaTN03sqPoURSarwU9R/wNF5Sff2zmBKKBy1oF7yIQTmNlxQxqD8whqRABhbMu6YVkiJoVkSXb6E/k6FE+yhPrzMoDSQFNHIsYBbVFa2RlIYWwm/UTe8gKaDXyTAOuqd1kgIAzCwgKQBA1EBSAICogaQAAFEDSQEAogaSAgBEjBB/B3o1C04w+m2JAAAAAElFTkSuQmCC" width="297" height="158" class="img_ev3q"></p>
<p>配置文件方面，定义<code>SPI</code>加载的目录为 <code>META-INF/shenyu/</code></p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token constant" style="color:#36acaa">SHENYU_DIRECTORY</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"META-INF/shenyu/"</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>系统启动时，会扫描 <code>SHENYU_DIRECTORY</code> 下的配置文件，并由 <code>ExtensionLoader</code> 类来加载所配置的<code>SPI</code>扩展类，并cache到内存中。  配置文件内容为 key=class的形式。 在系统执行期间， 由<code>ExtensionFactory</code>的实现类，返回key所对应的<code>SPI</code>实现类。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="shenyu-plugin的spi-实现">shenyu-plugin的<code>SPI</code> 实现<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI#shenyu-plugin%E7%9A%84spi-%E5%AE%9E%E7%8E%B0" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>在<em><strong>shenyu-plugin</strong></em>模组中，按照插件机制，实现了各种请求转发功能，包括支持request, redirect, response, rewrite等http协议功能，及 gRPC, dubbo, hystrix等微服务框架， 并且插件功能还在不断增加中。如果在各自的功能插件实做类中，还要做对routing 参数的解析等处理，不仅会造成程序的冗余，而且当要支持各自匹配规则，如通配符、正则表达式、SpEL解析等，会造成频繁对插件核心代码的修改。因此，在<em><strong>shenyu-plugin</strong></em>模组中，将routing参数解析做了更高一层的抽象，并按照<code>SPI</code>机制做了规则解析的实现。解析由三个部分组成：</p>
<ul>
<li class="">
<p><code>ParameterData</code>-参数资料,</p>
</li>
<li class="">
<p><code>PredictJudge</code>-断言</p>
</li>
<li class="">
<p><code>MatchStrategy</code>-匹配策略三个<code>SPI</code>实现。</p>
<p>这些扩展类定义在 <em><strong>shenyu-plugin-base</strong></em> module中，经过这样抽象后，每个插件实现中，routing 参数解析的功能全部由AbstractShenyuPlugin 来调用上述三个<code>SPI</code>工厂类来定义和实现。做到了功能的专一，并易于扩展，符合SOLID原则。</p>
</li>
</ul>
<p>本节就其中的<code>PredictJudge</code>-断言做详细解析。可以看到这个module中的pom文件中，添加了对***shenyu-<code>SPI</code>***的依赖</p>
<div class="language-xml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-xml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">dependency</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">groupId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">org.apache.shenyu</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">groupId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">artifactId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">shenyu-spi</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">artifactId</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">version</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">${project.version}</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">version</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">dependency</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="predicatejudge-spi-设计">PredicateJudge <code>SPI</code> 设计<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI#predicatejudge-spi-%E8%AE%BE%E8%AE%A1" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>PredicateJudge <code>SPI</code> 实现用来解析判断各类规则，当网关中配置的。这个类命名和功能都类似于java 的<a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html" target="_blank" rel="noopener noreferrer" class="">Predicate</a>  ，但对接受行为做了更进一步的抽象。这个<code>SPI</code>通过一个工厂和策略模式实现，首先来看<code>PredicateJudge</code> <code>SPI</code>接口的定义：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@SPI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token annotation punctuation" style="color:#393A34">@FunctionalInterface</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> </span><span class="token class-name">PredicateJudge</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * judge conditionData and realData is match.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param conditionData {@linkplain ConditionData}</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param realData       realData</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return true is pass  false is not pass.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">judge</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ConditionData</span><span class="token plain"> conditionData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> realData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>这部分的类图如下：</p>
<p>Fig 2-Predicate class diagram</p>
<p><img decoding="async" loading="lazy" alt="predicate-class-diagram" src="https://shenyu.apache.org/zh/assets/images/predicate-class-diagram-67a93b8c3e49800b23fe717c22027c54.png" width="763" height="347" class="img_ev3q"></p>
<p><code>PredicateJudgeFactory</code>的重要方法如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">PredicateJudge</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">newInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> operator</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">ExtensionLoader</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getExtensionLoader</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">PredicateJudge</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getJoin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">processSpecialOperator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">operator</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">Boolean</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">judge</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConditionData</span><span class="token plain"> conditionData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> realData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">conditionData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token class-name">StringUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isBlank</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">realData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">newInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">conditionData</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getOperator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">judge</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">conditionData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> realData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>这里<code>ConditionData</code>定义如下包含属性四个String类型的属性： <code>paramType, operator,paramName,paramValue</code></p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="paramtypeenum">ParamTypeEnum<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI#paramtypeenum" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>参数 <code>paramType</code>必须为系统中枚举类型 <code>ParamTypeEnum</code>，默认支持的<code>paramType</code>有：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">post</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> uri</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">query</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> host</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ip</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">header</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> cookie</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">req_method</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="operatorenum">OperatorEnum<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI#operatorenum" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p><code>operator</code> 必须为枚举类型 <code>OperatorEnum</code> ，目前支持的操作符有：（注意，严格区分大小写)</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">   match</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">regex</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> contains</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">SpEL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">  </span><span class="token class-name">Groovy</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">TimeBefore</span><span class="token punctuation" style="color:#393A34">,</span><span class="token class-name">TimeAfter</span><br></span></code></pre></div></div>
<p>基于以上的规则, plugin 模组实现了如下8个 <code>PredicateJudge</code> 实现类，分别实现上述operator的逻辑匹配规则.</p>
<table><thead><tr><th>Implementation class</th><th>Rule denotes 规则说明</th><th>corespondece operator</th></tr></thead><tbody><tr><td><code>ContainsPredicateJudge</code></td><td>包含关系 "contains"， 实际结果，需要包含所定规则的值</td><td>contains</td></tr><tr><td><code>EqualsPredicateJudge</code></td><td>相等"="，</td><td>=</td></tr><tr><td><code>MatchPredicateJudge</code></td><td>用于URI 路径匹配的处理</td><td>match</td></tr><tr><td><code>TimerAfterPredicateJudge</code></td><td>当前local时间是否晚于设定的时间</td><td>TimeAfter</td></tr><tr><td><code>TimerBeforePredicateJudge</code></td><td>当前local时间是否早于设定的时间</td><td>TimeBefore</td></tr><tr><td><code>GroovyPredicateJudge</code></td><td>Groovy,设定ParamName的值，与设定ParamValue相同</td><td>Groovy</td></tr><tr><td><code>RegexPredicateJudge</code></td><td>正则表达式匹配资料</td><td>regex</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="调用方法">调用方法<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI#%E8%B0%83%E7%94%A8%E6%96%B9%E6%B3%95" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>当要做一组参数的解析时，只需要调用<code>PredicateJudgeFactory</code>的judge方法即可：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token class-name">PredicateJudgeFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">judge</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ConditionData</span><span class="token plain"> conditionData</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> realData</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="spi配置文件"><code>SPI</code>配置文件<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI#spi%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>这些<code>PredicateJudge</code>实现类在  <code>SHENYU_DIRECTORY</code> 中的config文件中做了配置，在启动时会加加载并cache到内存中。</p>
<p><code>PredicateJudge</code>文件的内容如下，为key=class形式，左边的operator要和<code>ParamEnum</code>中的定义一致。</p>
<div class="language-properties codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-properties codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key attr-name" style="color:#00a4db">equals</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">org.apache.shenyu.plugin.base.condition.judge.EqualsPredicateJudge</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">contains</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">org.apache.shenyu.plugin.base.condition.judge.ContainsPredicateJudge</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">Groovy</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">org.apache.shenyu.plugin.base.condition.judge.GroovyPredicateJudge</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">match</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">org.apache.shenyu.plugin.base.condition.judge.MatchPredicateJudge</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">regex</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">org.apache.shenyu.plugin.base.condition.judge.RegexPredicateJudge</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">SpEL</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">org.apache.shenyu.plugin.base.condition.judge.SpELPredicateJudge</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">TimeAfter</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">org.apache.shenyu.plugin.base.condition.judge.TimerAfterPredicateJudge</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">TimeBefore</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">org.apache.shenyu.plugin.base.condition.judge.TimerBeforePredicateJudge</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="predicatejudge-spi在网关plugin中的使用">PredicateJudge <code>SPI</code>在网关Plugin中的使用<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI#predicatejudge-spi%E5%9C%A8%E7%BD%91%E5%85%B3plugin%E4%B8%AD%E7%9A%84%E4%BD%BF%E7%94%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>网关系统中，大部分的Plugin 都继承自<code>AbstractShenyuPlugin</code>，这个抽象类中，在做选择和规则解析时，调用了上述<code>SPI</code>中的<code>MatchStrategy</code>，继而在策略判断时调用<code>PredicateJudge</code> 的各个断言类来处理。</p>
<p>Plugin与<code>SPI</code> 的类图如下:</p>
<p>Fig 3- class diagram of plugins with PredicateJudge and <code>MatchStrategy</code> <code>SPI</code></p>
<p><img decoding="async" loading="lazy" alt="plugin-SPI-class-diagram" src="https://shenyu.apache.org/zh/assets/images/plugin-SPI-class-diagram-fa432591b833ff178cb662ce352f5b23.png" width="774" height="489" class="img_ev3q"></p>
<p>从客户端发来的请求，在系统中调用规则部分的<code>SPI</code>的流程如下：</p>
<p>Fig 4- flow chart for Shenyu gateway filter  with parameter processing</p>
<p><img decoding="async" loading="lazy" alt="SPI-flow-diagram" src="https://shenyu.apache.org/zh/assets/images/SPI-flow-diagram-590f2cd298ae7655330a62a2010b006e.png" width="975" height="472" class="img_ev3q"></p>
<ul>
<li class="">系统启动时，会加载目录下配置的<code>SPI</code>资料到内存中</li>
<li class="">当client有新的请求发到Apache shenyu 网关系统时，在网关内部，会调用对应的plugin</li>
<li class="">对实际请求资料做规则匹配时，会根据所包含的operator,调用的对应的PredicateJudge实现类</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="其他">其他<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI#%E5%85%B6%E4%BB%96" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="predicatejudge--判断结果举例">PredicateJudge  判断结果举例<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI#predicatejudge--%E5%88%A4%E6%96%AD%E7%BB%93%E6%9E%9C%E4%B8%BE%E4%BE%8B" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="containspredicatejudge---contains-rule">ContainsPredicateJudge- " contains“ rule<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-PredicateJudge-SPI#containspredicatejudge---contains-rule" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>举例：给定一组参数（ConditionData ）， paramType="uri", paramValue 是 "/http/**"</p>
<p>当应用 ContainsPredicateJudge包含关系时，判断结果如下表：</p>
<table><thead><tr><th>ConditionData  (operator="contains")</th><th>real data</th><th>judge result</th></tr></thead><tbody><tr><td>paramType="uri",    "/http/**"</td><td>"/http/**/test"</td><td>true</td></tr><tr><td></td><td>"/test/http/**/other"</td><td>true</td></tr><tr><td></td><td>"/http1/**"</td><td>false</td></tr></tbody></table>
<p>其他的几个PredicateJudge的具体功能可参考其代码和测试类.</p>]]></content>
        <author>
            <name>Huihui Yin</name>
        </author>
        <category label="SPI" term="SPI"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[RateLimiter SPI 代码分析]]></title>
        <id>https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI</id>
        <link href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[限流是网关必备的功能，用来应对高并发请求的场景。当系统受到异常攻击，短期内聚集了大量的流量；当有大量低级别的请求，处理这些请求会影响关键业务的处理，需要限制这些请求的访问速度; 或者系统内部出现一些异常，不能满负荷的服务整个应用请求等等。这些情况下，都需要启用限流来保护系统。可以拒绝服务、等待或降级处理，将流量限制到系统可接受的量，或者只允许某些域名(或某些业务)的请求优先处理。]]></summary>
        <content type="html"><![CDATA[<p>限流是网关必备的功能，用来应对高并发请求的场景。当系统受到异常攻击，短期内聚集了大量的流量；当有大量低级别的请求，处理这些请求会影响关键业务的处理，需要限制这些请求的访问速度; 或者系统内部出现一些异常，不能满负荷的服务整个应用请求等等。这些情况下，都需要启用限流来保护系统。可以拒绝服务、等待或降级处理，将流量限制到系统可接受的量，或者只允许某些域名(或某些业务)的请求优先处理。</p>
<p>针对以上的场景需求，在设计一个<code>API</code>网关的限流功能时，就需要考虑如下的扩展点：</p>
<ol>
<li class="">可以支持多种限流的算法，并易于扩展。</li>
<li class="">要可以支持多种限流的方式，能区分用户群、高低优先级的请求。</li>
<li class="">要支持高并发，能快速的做出限制或通过的决策。</li>
<li class="">要有容错处理，如果限流程序出错，网关系统能继续执行。</li>
</ol>
<p>本文会先介绍shenyu网关限流部分的总体技术架构，之后重点分析<code>RateLimiter</code> SPI扩展实现的代码。</p>
<blockquote>
<p>This article based on <code>shenyu-2.4.0</code> version of the source code analysis.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ratelimiter--总体设计说明">RateLimiter  总体设计说明<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI#ratelimiter--%E6%80%BB%E4%BD%93%E8%AE%BE%E8%AE%A1%E8%AF%B4%E6%98%8E" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>​        WebFlux是Spring 提供的基于Reactor模型的异步非阻塞框架，能提升吞吐量，使系统有更好的可伸缩性。Apache Shenyu网关的插件功能基于WebFlux框架实现的。RateLimiter功能是在<code>ratelimiter-plugin</code>中实现。在限流过程中，常用的算法有令牌桶、漏桶等算法，这些算法执行中，需要检核请求的来源，对已使用的流量做计数及逻辑计算，判定是否允许通过。为了提高并发及性能， 将计数和算法逻辑处理，都放到redis中。Java代码负责做数据参数的传递。在调用redis时，<a href="https://www.lua.org/" target="_blank" rel="noopener noreferrer" class="">lua</a>脚本可以常驻在redis内存中，能减少网络开销，并可以作为一个整体执行，具有原子性。<a href="https://spring.io/projects/spring-data-redis" target="_blank" rel="noopener noreferrer" class="">Spring Data Redis</a> 提供了对<a href="https://redis.io/commands" target="_blank" rel="noopener noreferrer" class="">redis命令</a>执行的抽象，执行序列化，及自动使用redis 脚本缓存。在这个plugin中，由于采用了reactor 非阻塞框架，所以采用Spring Redis Reactive类库实现对redis的功能调用。</p>
<p>​        这个plugin中的类包图如下，重点标出了与<code>RateLimiter</code> <code>SPI</code>相关的两个package: resolver 和algorithm.</p>
<p><img decoding="async" loading="lazy" alt="ratelimiter-package-diagram" src="https://shenyu.apache.org/zh/assets/images/ratelimiter-package-diagram-b041571cdf2f8592c23ab33bf07fbc71.png" width="976" height="617" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ratelimiter-spi的设计">RateLimiter SPI的设计<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI#ratelimiter-spi%E7%9A%84%E8%AE%BE%E8%AE%A1" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>由于采用了Spring data+ Redis +lua架构实现了高并发的需求。 如何做到对算法和限流方式的扩展呢？ Shenyu ratelimiter  plugin中设计了两个SPI来实现这两个需求：</p>
<ul>
<li class=""><code>RateLimiterAlgorithm</code>：用来扩展不同的限流算法。</li>
<li class=""><code>RateLimiterKeyResolver</code>： 用于扩展获取请求的关键信息，用于区分流量，例如按IP 地址、按某一段域名等来区分访问的请求。</li>
</ul>
<p>SPI的具体实作类与配置信息位于：<code>SHENYU_DIRECTORY</code>目录下 (默认在<code>/META-INF/shenyu</code>)下。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ratelimiterkeyresolver">RateLimiterKeyResolver<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI#ratelimiterkeyresolver" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>获取请求的关键信息，用于分组限流，例如按URL/ 用户 / IP 等， <code>RateLimiterKeyResolver</code> 接口定义如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@SPI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> </span><span class="token class-name">RateLimiterKeyResolver</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * get Key resolver's name.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return Key resolver's name</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getKeyResolverName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * resolve.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param exchange exchange the current server exchange {@linkplain ServerWebExchange}</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return rate limiter key</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">resolve</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p><code>@SPI</code>将当前interface 注册为Shenyu SPI 接口。resolve(ServerWebExchange exchange)方法用来提供解析方式。</p>
<p>RateLimiterKeyResolver  SPI 提供了两种key resolver, <code>WholeKeyResolve</code>和 <code>RemoteAddrKeyResolver</code>，其中<code>RemoteAddrKeyResolver</code>中的<code>resolve</code>方法代码如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">resolve</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Objects</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">requireNonNull</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequest</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRemoteAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getHostAddress</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>其key值为请求的IP地址。 基于SPI及工厂类的实现，可以非常方便的扩展实现新的key resolver，如URL,用户等等。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ratelimiteralgorithm-spi">RateLimiterAlgorithm SPI<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI#ratelimiteralgorithm-spi" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p><code>RateLimiterAlgorithm</code> SPI 用来实现对不同限流算法的识别、加载和定义，其类图如下：</p>
<p><img decoding="async" loading="lazy" alt="ratelimiteral-class-diagram" src="https://shenyu.apache.org/zh/assets/images/ratelimiteral-class-diagram-24df4785848602bdc5b321cf609d5cda.png" width="1010" height="752" class="img_ev3q"></p>
<p>本模组使用了工厂模式，提供了接口类、抽象类和工厂类，提供了4个实现类，其中实现类对应的Lua脚本在 <code>RateLimitEnum</code> 中做了定义，放置在 <code>/META-INF/scripts</code> 目录下。接口<code>RateLimiterAlgorithm</code>的代码如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token annotation punctuation" style="color:#393A34">@SPI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> </span><span class="token class-name">RateLimiterAlgorithm</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">RedisScript</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">T</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getScript</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getKeys</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">String</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Callback string.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param script the script</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param keys the keys</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param scriptArgs the script args</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">default</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">callback</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RedisScript</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> script</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> keys</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> scriptArgs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>@SPI</code> 将这个接口注册为shenyu SPI, 其中定义了三个方法：</p>
<ul>
<li class=""><code>getScript()</code> 方法返回一个 <code>RedisScript</code>对象，这个对象将传递给Redis。</li>
<li class=""><code>getKeys(String id)</code> 返回一个键值的List.</li>
<li class=""><code>callback()</code>回调函数用于异步处理一些需要在返回后做的处理，缺省是空方法。</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="抽象类-abstractratelimiteralgorithm">抽象类 AbstractRateLimiterAlgorithm<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI#%E6%8A%BD%E8%B1%A1%E7%B1%BB-abstractratelimiteralgorithm" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>在这个类中，实现了接口的模板方法，使用参数类型为<code>List&lt;Long&gt;</code>,  抽象方法getScriptName() 和getKeyName() 留给各个实作类来实现。如下的getScript() 是这个类中读取lua脚本的处理代码。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">RedisScript</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Long</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getScript</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">initialized</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">DefaultRedisScript</span><span class="token plain"> redisScript </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">DefaultRedisScript</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token class-name">String</span><span class="token plain"> scriptPath </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/META-INF/scripts/"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getScriptName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            redisScript</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setScriptSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ResourceScriptSource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ClassPathResource</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">scriptPath</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            redisScript</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setResultType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">List</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">script </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> redisScript</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            initialized</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">compareAndSet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> redisScript</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> script</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p><code>AtomicBoolean</code>类型的变量<code>initialized</code> 用来标记lua脚本是否有被加载。 如果还没有加载，就从/META-INF/scripts/目录下，读取<code>scriptName</code>指定的Lua文件，加载成<code>RedisScript</code>对象。指定结果为<code>List</code>类型， 设定量<code>initialized</code>为true,避免重复加载。 返回 <code>RedisScript</code>对象。</p>
<p><code>AbstractRateLimiterAlgorithm</code>中<code>getKeys()</code>的代码如下，</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getKeys</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> prefix </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getKeyName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">".{"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> tokenKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> prefix </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"}.tokens"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> timestampKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> prefix </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"}.timestamp"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Arrays</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">asList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">tokenKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> timestampKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>这个模板方法中，产生了两个字符串，其中，<code>tokenKey</code>会作为Key传递给<code>redis</code>, 指向一个有序集合。 <code>timestampKey</code>是一个以传入id 为识别的字符串。</p>
<p>可以从上面的类图中看到，<code>ConcurrentRateLimiterAlgorithm</code> 和<code>SlidingWindowRateLimiterAlgorithm</code> 有覆写<code>getKeys(String id)</code>方法，而两外两个算法程序，则采用的是抽象类中的实现。也只有 <code>ConcurrentRateLimiterAlgorithm</code> 重写了<code>callback()</code>方法。下文中我们会对此做进一步的分析。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="工厂类ratelimiteralgorithmfactory">工厂类RateLimiterAlgorithmFactory<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI#%E5%B7%A5%E5%8E%82%E7%B1%BBratelimiteralgorithmfactory" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p><code>RateLimiterAlgorithmFactory</code> 中依据算法名称，获取RateLimiterAlgorithm实例的方法代码如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">static</span><span class="token plain"> </span><span class="token class-name">RateLimiterAlgorithm</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">newInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> name</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ExtensionLoader</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getExtensionLoader</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">RateLimiterAlgorithm</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getJoin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">orElse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">TokenBucketRateLimiterAlgorithm</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>按照Apache shenyu SPI的规则，由加载器<code>ExtensionLoader</code>获得实作类，当找不到算法时，默认返回令牌桶算法实现类。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="与redis做资料交互">与Redis做资料交互<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI#%E4%B8%8Eredis%E5%81%9A%E8%B5%84%E6%96%99%E4%BA%A4%E4%BA%92" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>从上面代码我们了解到Apache Shenyu网关中，RateLimiter SPI 的基本扩展点，在Shenyu网关运行中，应用ReactiveRedisTemplate 来异步执行对redis的调用处理。实现代码在RedisRateLimiter类的isAllowed()方法中，其部分代码如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">RateLimiterResponse</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">isAllowed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RateLimiterHandle</span><span class="token plain"> limiterHandle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// get parameters that will pass to redis from RateLimiterHandle Object</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">double</span><span class="token plain"> replenishRate </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> limiterHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getReplenishRate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">double</span><span class="token plain"> burstCapacity </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> limiterHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getBurstCapacity</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">double</span><span class="token plain"> requestCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> limiterHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getRequestCount</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// get the current used RateLimiterAlgorithm</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">RateLimiterAlgorithm</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> rateLimiterAlgorithm </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RateLimiterAlgorithmFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">limiterHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getAlgorithmName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Flux</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Long</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> resultFlux </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Singleton</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INST</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ReactiveRedisTemplate</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">script</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> keys</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> scriptArgs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> resultFlux</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onErrorResume</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">throwable </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Flux</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">just</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">Arrays</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">asList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1L</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">1L</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">reduce</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">ArrayList</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Long</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">longs</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> l</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    longs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">addAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">l</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> longs</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">results </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">boolean</span><span class="token plain"> allowed </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> results</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1L</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token class-name">Long</span><span class="token plain"> tokensLeft </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> results</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">RateLimiterResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">allowed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> tokensLeft</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doOnError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">throwable </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> log</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Error occurred while judging if user is allowed by RedisRateLimiter:{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> throwable</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">doFinally</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">signalType </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> rateLimiterAlgorithm</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">callback</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">script</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> keys</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> scriptArgs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>POJO 对象RateLimiterHandle 中，定义了限流所需的属性算法名称, 速录，容量，请求的数量 。首先 从limiterHandle 包装类中取得需要传入redis的几个参数。之后从RateLimiterAlgorithmFactory 从工厂类取得当前配置的限流算法。 之后做Key值和参数的传递。</p>
<p>为了更方便阅读，下图给出了java代码与redis执行参数输入、输出的传递过程。左边是<code>isAllowed</code>() 函数的后半部分代码，右边是一个Lua脚本的输入输出代码。</p>
<p>下面说明Java代码的执行过程：</p>
<ol>
<li class="">
<p>从<code>getKeys()</code>方法获得两个键值<code>List&lt;String&gt;</code>. 其中第一个Key会映射为Redis中的有序集合。</p>
</li>
<li class="">
<p>设定4个参数：速率 replenishRate ,容量 burstCapacity, 时间戳， 返回当前java 纪元秒数(长整数)EpochSecond, 请求的数量 requestcount.</p>
</li>
<li class="">
<p>按所设定的脚本、Key值、参数调用<code>ReactiveRedisTemplate</code>功能，执行redis处理。返回参数是<code>Flux&lt;List&lt;Long&gt;&gt;</code>类型</p>
</li>
<li class="">
<p>通过reduce方法将其返回值从<code>Flux&lt;ArrayList&lt;Long&gt;&gt;</code> 类型转换为<code>Mono&lt;ArrayList&lt;Long&gt;&gt;</code>，再经过map方法，转换为<code>Mono&lt;RateLimiterResponse&gt;</code>返回。</p>
<p>返回结果有两个资料，allowed =1, 代表允许通过，0-不通过；而第二个返回参数tokensLeft，是可用的剩余请求数量。</p>
</li>
</ol>
<p>5.容错性方面，由于使用的是reactor 的非阻塞通讯模型，当发生错误时，会执行onErrorResume()语句，Flux.just产生返回资料， 默认为<code>allowed</code>=1, 代表允许通过， 并丢出错误日志。</p>
<p>6.之后执行doFinally()方法,执行算法实现类的callback方法。</p>
<p><img decoding="async" loading="lazy" alt="io-with-lua" src="https://shenyu.apache.org/zh/assets/images/io-with-lua-eefcd28d4b59a8bd0e69e29400018c50.png" width="845" height="566" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4种限流算法">4种限流算法<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI#4%E7%A7%8D%E9%99%90%E6%B5%81%E7%AE%97%E6%B3%95" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>上面我们了解了网关中如何通过Java代码如何与Redis 做通讯，这一节我们通过简要分析网关中提供的4种限流算法中的一些代码，来理解如何开发使用<code>RateLimiter SPI</code>的接口方法,并与Redis有效协作。</p>
<p><code>Ratelimiter SPI</code>目前提供了4种限流算法:</p>
<table><thead><tr><th>Algorithm name</th><th>Java class</th><th>Lua script file</th></tr></thead><tbody><tr><td>Request rate limiter</td><td><code>TokenBucketRateLimiterAlgorithm</code></td><td>request_rate_limiter.lua</td></tr><tr><td>Slide window rate limiter</td><td><code>SlidingWindowRateLimiterAlgorithm</code></td><td>liding_window_request_rate_limiter.lua</td></tr><tr><td>Concurrent rate limiter</td><td><code>ConcurrentRateLimiterAlgorithm</code></td><td>concurrent_request_rate_limiter.lua</td></tr><tr><td>Leaky bucket algorithm</td><td><code>LeakyBucketRateLimiterAlgorithm</code></td><td>request_leaky_rate_limiter.lua</td></tr></tbody></table>
<ol>
<li class="">令牌桶限流：按请求数量限流，设置每秒N个请求，超过N的请求会拒绝服务。算法实现时，以时间间隔计算匀速产生令牌的数量。若每次请求的数量，小于桶内令牌的数量，则允许通过。 时间窗口为 2*容积/速率。</li>
<li class="">滑动窗口限流：与令牌桶限流不同在于，其窗口大小比令牌桶的窗口小，为一个容积/速率。并且每次移动向后一个时间时间窗口。其他限流原理与令牌桶类似。</li>
<li class="">并发的请求速率限流：严格限制并发访问量为N个请求，大于N的请求会被拒绝。每次当有新请求，查看计数是否大于N, 若小于N则允许通过，计数加1。 当这个请求调用结束时，会释放这个信号（计数减1）</li>
<li class="">漏桶算法:  相对于令牌桶算法，漏桶算法有助于减少流量聚集，实现更为平滑的限流处理。 漏桶算法强制以常数N的速率输出流量，其以漏桶为模型，可漏水的量为时间间隔 *速率。若可漏水量&gt;已使用量，则已使用量设为0( 清空漏桶)，否则已使用量要减去可漏水量。  若请求数量+ 已使用量&lt; 总容量，则允许请求通过。</li>
</ol>
<p>下面以 并行限流算法为例，解读Lua和Java代码，查看callback 方法的使用。 通过解读令牌桶和滑动窗口算法代码，了解getKey()方法的使用。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="并发请求数限流中使用callback方法">并发请求数限流中使用callback方法<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI#%E5%B9%B6%E5%8F%91%E8%AF%B7%E6%B1%82%E6%95%B0%E9%99%90%E6%B5%81%E4%B8%AD%E4%BD%BF%E7%94%A8callback%E6%96%B9%E6%B3%95" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>首先<code>ConcurrentRateLimiterAlgorithm</code> 的<code>getKeys()</code> 方法覆写了抽象类中的模板方法：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getKeys</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> tokenKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">getKeyName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">".{"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> id </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"}.tokens"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">String</span><span class="token plain"> requestKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">UUIDUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">generateShortUuid</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">Arrays</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">asList</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">tokenKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> requestKey</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>第二个元素 requestKey 是一个long型不重复值(由一个分布式ID产生器产生的，递增，比当前时间EpochSecond小)， 相应的concurrent_request_rate_limiter.lua的代码：</p>
<div class="language-lua codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-lua codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> KEYS</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> capacity </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tonumber</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ARGV</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> timestamp </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tonumber</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ARGV</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> id </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> KEYS</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">]</span><br></span></code></pre></div></div>
<p>这里id 即是取得上面的getKeys()方法产生的requestKey， 一个uuid.  后续的处理如下：</p>
<div class="language-lua codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-lua codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> count </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> redis</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"zcard"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> allowed </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> count </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> capacity </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  redis</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"zadd"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> timestamp</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  allowed </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  count </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> count </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">end</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> allowed</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> count </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>先用zcard命令统计redis中key值所对应的有序集合中的元素个数，若元素总数count小于容量，则允许通过，并用zadd key score member方法，向key所在的有序集合中，添加一个元素id, 其score为timestamp.  则此时元素的总个数count实际为count+1.</p>
<p>以上的代码都是在redis中作为一个原子操作来执行的。当同一个key (例如Ip下)有大量并发请求时，redis记录的该ip的有序集合的数量count也在不断累加中。当超过容量限制，则会拒绝服务。</p>
<p>并发请求数限流算法中，要求当请求调用结束时，要释放这个信号量，lua代码中并没有做这个处理。</p>
<p>我们来看看 <code>ConcurrentRateLimiterAlgorithm</code>类中的回调函数：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@Override</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token annotation punctuation" style="color:#393A34">@SuppressWarnings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"unchecked"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">callback</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RedisScript</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics operator" style="color:#393A34">?</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> script</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> keys</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">List</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">String</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> scriptArgs</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Singleton</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INST</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ReactiveRedisTemplate</span><span class="token punctuation" style="color:#393A34">.</span><span class="token keyword" style="color:#00009f">class</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">opsForZSet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">remove</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">keys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> keys</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">subscribe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>这里做了一个异步的订阅处理，通过<code>ReactiveRedisTemplate</code>删除redis中(key, id)的元素，等待调用结束后，释放这个信号。这个remove的处理不能放到lua脚本中执行，否则逻辑就是错误的。这也正是<code>RateLimiterAlgorithm</code> SPI 设计<code>callback</code>方法的用意。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="令牌桶算法中使用getkeys">令牌桶算法中使用getKeys()<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI#%E4%BB%A4%E7%89%8C%E6%A1%B6%E7%AE%97%E6%B3%95%E4%B8%AD%E4%BD%BF%E7%94%A8getkeys" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>对应的Lua 代码如下：</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">local tokens_key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">KEYS</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">local timestamp_key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">KEYS</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">]</span><br></span></code></pre></div></div>
<p>省略获取参数的代码</p>
<div class="language-lua codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-lua codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> fill_time </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> capacity</span><span class="token operator" style="color:#393A34">/</span><span class="token plain">rate</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> ttl </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> math</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">floor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">fill_time</span><span class="token operator" style="color:#393A34">*</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre></div></div>
<p>时间窗口ttl 大概是 2* 容量/速率.</p>
<div class="language-lua codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-lua codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> last_tokens </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tonumber</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">redis</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"get"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> tokens_key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> last_tokens </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">nil</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  last_tokens </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> capacity</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">end</span><br></span></code></pre></div></div>
<p>从有序集合中取得上次使用的token,如果没有则last_tokens = 容量。</p>
<div class="language-lua codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-lua codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> last_refreshed </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tonumber</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">redis</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"get"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> timestamp_key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> last_refreshed </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">nil</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  last_refreshed </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">end</span><br></span></code></pre></div></div>
<p>以timestamp_key为key,从有序集合中取得上次刷新时间，默认为0.</p>
<div class="language-lua codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-lua codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> delta </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> math</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">max</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> now</span><span class="token operator" style="color:#393A34">-</span><span class="token plain">last_refreshed</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> filled_tokens </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> math</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">min</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">capacity</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> last_tokens</span><span class="token operator" style="color:#393A34">+</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">delta</span><span class="token operator" style="color:#393A34">*</span><span class="token plain">rate</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> allowed </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> filled_tokens </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> requested</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> allowed_num </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> allowed </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  new_tokens </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> filled_tokens </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> requested</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  allowed_num </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">end</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>时间间隔*速率匀速产生令牌，若令牌数量&gt;请求数量，则allowed=1, 并且更新令牌数量。</p>
<div class="language-lua codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-lua codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">redis</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"setex"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> tokens_key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ttl</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> new_tokens</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">redis</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"setex"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> timestamp_key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ttl</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> now</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> allowed_num</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> new_tokens </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>这里now是传入的当前时间(EpochSecond)，设置<code>tokens_key</code>所对应的有序集合的值为 <code>new_tokens</code>（即新令牌数量) ， 过期时间为<code>ttl</code>。 更新集合中，<code>timestamp_key</code>的值为当前时间，过期时间为<code>ttl</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="滑动窗口算法中使用getkeys方法">滑动窗口算法中使用<code>getKeys</code>方法<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI#%E6%BB%91%E5%8A%A8%E7%AA%97%E5%8F%A3%E7%AE%97%E6%B3%95%E4%B8%AD%E4%BD%BF%E7%94%A8getkeys%E6%96%B9%E6%B3%95" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>在<code>SlidingWindowRateLimiterAlgorithm</code> 的<code>getKeys()</code>同样覆写了父类，代码与<code>ConcurrentRateLimiterAlgorithm</code> 方法代码一致。</p>
<p>如下为滑动窗口算法的Lua代码，省略了其他参数的接收代码。</p>
<div class="language-lua codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-lua codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> timestamp_key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> KEYS</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">......</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> window_size </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tonumber</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">capacity </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> rate</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> window_time </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><br></span></code></pre></div></div>
<p>设定窗口大小为容积/速率。</p>
<div class="language-lua codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-lua codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> last_requested </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> exists_key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> redis</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'exists'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> tokens_key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exists_key </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    last_requested </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> redis</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'zcard'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> tokens_key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">end</span><br></span></code></pre></div></div>
<p>获取当前key 的基数</p>
<div class="language-lua codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-lua codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> remain_request </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> capacity </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> last_requested</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">local</span><span class="token plain"> allowed_num </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">last_requested </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> capacity</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    allowed_num </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    redis</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'zadd'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> tokens_key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> now</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> timestamp_key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">end</span><br></span></code></pre></div></div>
<p>计算剩余可用量 = 容量 减去已使用量，若<code>last_requested</code> &lt; capacity ,则允许通过，并且在<code>tokens_key</code>为key的有序集合中，增加一个 元素（key =<code>timestam_key</code>,value= <code>now</code>)</p>
<div class="language-lua codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-lua codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">redis</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'zremrangebyscore'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> tokens_key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> now </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> window_size </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> window_time</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">redis</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">call</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'expire'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> tokens_key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> window_size</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> allowed_num</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> remain_request </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>前面已经设定<code>window_time</code>=1, 用Redis的 <code>zremrangebyscore</code>命令，移除有序集合中，score为[0- 当前时间-窗口大小]的元素，即移动一个窗口大小。设定tokens_key的过期时间为窗口大小。</p>
<p>在<code>AbstractRateLimiterAlgorithm</code>的模板方法中，<code>getKeys(final String id)</code> 给出的第二个值(以<code>secondKey</code>指代)，是拼接了{id} (即resolve key)的一个固定字符串。从上面三个算法代码可以看到，在令牌桶算法中，<code>secondKey</code>在Lua代码执行中会更新为最新的时间，所以无所谓传入的值。而在并发限流算法中，会以此<code>secondKey</code>为条件，在java <code>callback</code>方法中移除对应的元素。而在滑动窗口算法中，这个<code>secondKey</code>的值，会作为一个新元素的key, 增加到当前有序集合中，并在做窗口滑动中，过期的资料会被删除掉。</p>
<p>总之，当设计新的限流算法时，要根据算法需要仔细设计<code>getKey()</code>方法。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="如何调用-ratelimiter-spi">如何调用 RateLimiter SPI<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI#%E5%A6%82%E4%BD%95%E8%B0%83%E7%94%A8-ratelimiter-spi" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>在<code>RateLimiter</code> Plug中的<code>doExecute()</code>方法中，传入的三个参数 exchange 为请求的连接， chain 为shenyu插件的调用链，selector 是选择器，rule是系统中配置的规则参数资料。</p>
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">protected</span><span class="token plain"> </span><span class="token class-name">Mono</span><span class="token generics punctuation" style="color:#393A34">&lt;</span><span class="token generics class-name">Void</span><span class="token generics punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">doExecute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ServerWebExchange</span><span class="token plain"> exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">ShenyuPluginChain</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">SelectorData</span><span class="token plain"> selector</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">final</span><span class="token plain"> </span><span class="token class-name">RuleData</span><span class="token plain"> rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">RateLimiterHandle</span><span class="token plain"> limiterHandle </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">RatelimiterRuleHandleCache</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">obtainHandle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">CacheKeyUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">INST</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getKey</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rule</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">String</span><span class="token plain"> resolverKey </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">ofNullable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">limiterHandle</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getKeyResolverName</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flatMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">Optional</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">of</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"-"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token class-name">RateLimiterKeyResolverFactory</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">newInstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">resolve</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">orElse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> redisRateLimiter</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isAllowed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rule</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getId</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> resolverKey</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> limiterHandle</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">flatMap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">response </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">!</span><span class="token plain">response</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">isAllowed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                exchange</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">setStatusCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">HttpStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TOO_MANY_REQUESTS</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token class-name">Object</span><span class="token plain"> error </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">ShenyuResultWrap</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token class-name">ShenyuResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TOO_MANY_REQUESTS</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token class-name">ShenyuResultEnum</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">TOO_MANY_REQUESTS</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getMsg</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token class-name">WebFluxResultUtils</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">result</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> chain</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">exchange</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>1.首先，从缓存中，取得系统设定的限流参数<code>RateLimiterHandle</code>实例 <code>limiterHandle</code>.
2.根据name指定的Resolver 获得请求的连接Key信息（如地址等).
3.调用 RedisRateLimiter的 isAllowed方法, 获取返回值后，
4.若<code>isAllowd</code>=false,做错误处理
5.如果 <code>isAllowed</code>=true，return chain.execute(exchange)， 对该请求做后续处理，传递到调用链的下一关。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://shenyu.apache.org/zh/blog/SPI-SourceCode-Analysis-RateLimiter-SPI#summary" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>整个<code>RateLimiter</code> plugin框架基于Spring WebFlux开发，用redis 和lua脚本做限流计数及核心逻辑处理，支持高并发及弹性扩展。</p>
<ol>
<li class="">
<p><code>RateLimiter</code> <code>SPI</code> 提供了两个<code>SPI</code> 接口，通过应用面向接口设计及各种设计模式，可以方便的增加新的限流算法，以及各种流量解析规则。</p>
</li>
<li class="">
<p>提供了令牌桶、并发速率限流、滑动窗口、漏桶4种限流算法。在设计算法实现时，需要根据算法特征设计KEY值，用Lua脚本实现在redis中要处理的逻辑，设计<code>callback()</code>方法做后续的数据处理。</p>
</li>
<li class="">
<p>响应式编程，实现过程简洁高效。</p>
</li>
</ol>]]></content>
        <author>
            <name>Huihui Yin</name>
            <uri>https://github.com/changanjennifer/</uri>
        </author>
        <category label="rate limiter" term="rate limiter"/>
        <category label="SPI" term="SPI"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[社区新人开发者启动及开发防踩坑指南]]></title>
        <id>https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor</id>
        <link href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor"/>
        <updated>2026-01-23T10:37:48.000Z</updated>
        <summary type="html"><![CDATA[前言]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="前言">前言<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>作为 <code>Shenyu</code> 社区初来乍到的开发者，我在按照相关教程进行项目启动及开发的过程中，遇到了一些教程中并未提及到的 “坑” ， 我将我启动<code>shenyu</code> , <code>shenyu-dashboard</code>, <code>shenyu-website</code> 的详细步骤记录在这篇博客中，希望可以帮到社区中更多的新人开发者。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="环境准备">环境准备<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E7%8E%AF%E5%A2%83%E5%87%86%E5%A4%87" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<ul>
<li class="">本地正确安装 <code>JDK17</code> 或更高版本</li>
<li class="">本地正确安装 <code>Git</code></li>
<li class="">本地正确安装<code>Maven3.63</code> 或更高版本</li>
<li class="">选择一款开发工具，本文使用 <code>IDEA</code> 为例</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="shenyu-后端启动指南">ShenYu 后端启动指南<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#shenyu-%E5%90%8E%E7%AB%AF%E5%90%AF%E5%8A%A8%E6%8C%87%E5%8D%97" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="安装并配置maven">安装并配置Maven<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E5%AE%89%E8%A3%85%E5%B9%B6%E9%85%8D%E7%BD%AEmaven" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>Maven是一个跨平台的项目管理工具。作为Apache组织顶级开源项目，其主要服务于基于Java平台的项目创建，依赖管理和项目信息管理。</p>
<ol>
<li class="">
<p><a href="https://maven.apache.org/download.cgi" target="_blank" rel="noopener noreferrer" class="">下载 maven</a>，并解压到一个没有中文没有空格的路径下。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/maven-install-1810a86409d255c485e91852e679baad.png" width="1029" height="238" class="img_ev3q"></p>
</li>
<li class="">
<p>将 <code>maven</code> 目录下的 <code>bin</code> 目录添加至环境变量中。以 <code>Windows</code> 为例，若下载目录为 <code>E:\apache-maven-3.9.1</code> ，则将<code>E:\apache-maven-3.9.1\bin</code> 添加至 <code>Path</code> 系统变量中。</p>
</li>
<li class="">
<p>验证是否安装成功。在命令行窗口中输入 <code>mvn -v</code> ，若出现 Maven 版本及 Java 版本即为安装成功。如下所示：</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">C:\Users\pc&gt;mvn -v</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Apache Maven 3.9.1 (2e178502fcdbffc201671fb2537d0cb4b4cc58f8)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Maven home: E:\apache-maven-3.9.1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Java version: 18.0.1.1, vendor: Oracle Corporation, runtime: C:\Program Files\Java\jdk-18.0.1.1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Default locale: zh_CN, platform encoding: UTF-8</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"</span><br></span></code></pre></div></div>
</li>
<li class="">
<p>为了加快项目相关依赖的下载速度，需要更改 Maven 镜像，此处添加阿里云等镜像。将 <code>conf/settings.xml</code> 中 <code>&lt;mirrors&gt; &lt;/mirrors&gt;</code> 标签对更改为以下内容：</p>
<div class="language-xml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-xml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">mirrors</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">mirror</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">alimaven</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">name</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">aliyun maven</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">name</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">url</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">http://maven.aliyun.com/nexus/content/groups/public/</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">url</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">mirrorOf</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">central</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">mirrorOf</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">mirror</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">mirror</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">alimaven</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">mirrorOf</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">central</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">mirrorOf</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">name</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">aliyun maven</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">name</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">url</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">http://maven.aliyun.com/nexus/content/repositories/central/</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">url</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">mirror</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">mirror</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">maven</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">mirrorOf</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">central</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">mirrorOf</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">name</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">name_</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">name</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">url</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">http://repo1.maven.org/maven2</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">url</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">mirror</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">mirror</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">junit</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">id</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">mirrorOf</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">central</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">mirrorOf</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">name</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">junit address/</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">name</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">url</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">http://jcenter.bintray.com/</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">url</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">mirror</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">mirrors</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<p>并在 <code>&lt;/mirrors&gt;</code> 下一行添加 <code>&lt;localRepository&gt;E:/maven_local_repository&lt;/localRepository&gt;</code>设置 Maven 本地仓库位置。具体位置可自行指定。</p>
</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="拉取-shenyu-代码">拉取 ShenYu 代码<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E6%8B%89%E5%8F%96-shenyu-%E4%BB%A3%E7%A0%81" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<ol>
<li class="">
<p>在 Github 上 Fork <a href="https://github.com/apache/shenyu" target="_blank" rel="noopener noreferrer" class="">ShenYu</a> 仓库到自己的存储库中，以后可在此仓库中进行开发并提交 PR</p>
</li>
<li class="">
<p>使用 Git 将上一步 Fork 的仓库下载到本地：</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">git clone git@github.com:${YOUR_USERNAME}/${TARGET_REPO}.git</span><br></span></code></pre></div></div>
<p>若提示文件名过长，则通过命令行执行下面的命令：</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">git config --global core.longpaths true</span><br></span></code></pre></div></div>
<p>Tips: 如果提示如下错误或者网络不好无法拉取全部代码：</p>
<div class="language-tex codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-tex codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">RPC failed; curl 92 HTTP/2 stream 5 was not closed cleanly: CANCEL (err 8) 2057 bytes of body are still expected fetch-pack: unexpected disconnect while reading sideband packet early EOF fetch-pack: invalid index-pack output</span><br></span></code></pre></div></div>
<p>可以执行以下命令先拉取一个版本的代码,然后在获取全量代码.</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">git clone https://github.com/apache/shenyu.git --depth 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cd ./shenyu</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">git fetch --unshallow</span><br></span></code></pre></div></div>
</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="shenyu-初启动">ShenYu 初启动<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#shenyu-%E5%88%9D%E5%90%AF%E5%8A%A8" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="准备工作">准备工作<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ol>
<li class="">
<p>在 <code>shenyu</code> 目录下使用 Maven 进行编译：</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">mvn clean install -Dmaven.javadoc.skip=true -B -Drat.skip=true -Djacoco.skip=true -DskipITs -DskipTests</span><br></span></code></pre></div></div>
</li>
<li class="">
<p>配置 IDEA 环境。使用 IDEA 打开 <code>shenyu</code> 项目，点击左上角 <code>File</code> -&gt; <code>Settings</code> ，按照下图配置  Maven 。其中 <code>User settings file</code> 选择你的 <code>settings.xml</code> 所在目录， <code>Local repository</code> 会自动加载 <code>settings.xml</code> 中设置的 <code>localRepository</code> 路径：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/idea-config-eab162e57c60c188ae39b46d08d17d0a.png" width="1471" height="1004" class="img_ev3q"></p>
</li>
<li class="">
<p>此时，IDEA 会自动下载项目相关依赖，需等待一会，完成后如下图所示：</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/project-without-example-0a8dc1e81a325b6ce56328b3d282325d.png" width="480" height="866" class="img_ev3q"></p>
<p>可以发现， <code>shenyu-e2e</code>, <code>shenyu-examples</code>, <code>shenyu-integrated-test</code> 没有被 IDEA 标记为 Maven 项目，需手动添加。分别选中包中的 <code>pom.xml</code> 文件，右键点击 <code>Add as Maven Project</code> 。
若 shenyu-e2e 构建失败，则将其 <code>pom.xml</code> 中 <code>&lt;relativePath&gt;./pom.xml&lt;/relativePath&gt;</code> 改为 <code>&lt;relativePath/&gt;</code> 。</p>
</li>
</ol>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="启动网关服务">启动网关服务<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E5%90%AF%E5%8A%A8%E7%BD%91%E5%85%B3%E6%9C%8D%E5%8A%A1" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ol>
<li class="">
<p>启动 <code>shenyu-admin</code> 控制台（默认使用H2数据库）</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/admin-debdd1ee5e979a4892f26e4d54572ead.png" width="642" height="603" class="img_ev3q"></p>
</li>
<li class="">
<p>启动 <code>shenyu-bootstrap</code></p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/bootstrap-cafa4d22b0d69bb6ee82c01e7b45d239.png" width="408" height="185" class="img_ev3q"></p>
</li>
</ol>
<blockquote>
<p>到这一步，shenyu网关已经启动。</p>
<p>我们可以打开浏览器，访问admin控制台：<a href="http://localhost:9095/" target="_blank" rel="noopener noreferrer" class="">http://localhost:9095/</a></p>
<p>默认账号：admin ，默认密码：123456</p>
</blockquote>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="启动应用服务">启动应用服务<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E5%90%AF%E5%8A%A8%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>Apache ShenYu提供了Http、Dubbo、SpringCloud等应用接入shenyu网关的样例，位于 <code>shenyu-example</code> 模块，这里以Http服务为例。</p>
<p>启动 <code>shenyu-examples-http</code>。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/shenyu-examples-http-16e2cd3166eb89067d20ab76fbd2000a.png" width="1013" height="578" class="img_ev3q"></p>
<p>这时，<code>shenyu-examples-http</code> 会自动把加 <code>@ShenyuSpringMvcClient</code> 注解的接口方法，以及application.yml中的相关配置注册到网关。我们打开 <a href="http://localhost:9095/" target="_blank" rel="noopener noreferrer" class="">admin控制台</a>，即可在<code>插件列表 -&gt; Proxy -&gt; divide</code> 中看到相关配置。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="测试http请求">测试Http请求<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E6%B5%8B%E8%AF%95http%E8%AF%B7%E6%B1%82" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>下面使用 <code>IDEA HTTP Client Plugin</code> 模拟 http 的方式来访问 http 服务。</p>
<ul>
<li class="">
<p>本地访问，不使用 shenyu 代理</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/shenyu-http-test-api-local-0769bf0aa49ba1d1bf19781429c0311b.png" width="1807" height="869" class="img_ev3q"></p>
</li>
<li class="">
<p>使用 shenyu 代理</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/shenyu-http-test-api-b3f37741aee04845e891179e8eb6a137.png" width="1855" height="895" class="img_ev3q"></p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="使用更多插件">使用更多插件<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E4%BD%BF%E7%94%A8%E6%9B%B4%E5%A4%9A%E6%8F%92%E4%BB%B6" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>我们可以参考 <a href="https://shenyu.apache.org/zh/docs/index" target="_blank" rel="noopener noreferrer" class="">官方文档</a>左侧<code>插件集合</code>，来使用所需要插件。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="shenyu-前端启动指南">Shenyu 前端启动指南<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#shenyu-%E5%89%8D%E7%AB%AF%E5%90%AF%E5%8A%A8%E6%8C%87%E5%8D%97" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="安装-nodejs">安装 Node.js<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E5%AE%89%E8%A3%85-nodejs" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="下载">下载<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E4%B8%8B%E8%BD%BD" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<ol>
<li class="">
<p>在<a href="https://nodejs.org/en" target="_blank" rel="noopener noreferrer" class="">官网</a>下载并安装Node.js ，选择 <code>LTS</code> 版本即可</p>
</li>
<li class="">
<p>安装时，除了设置安装路径，其他一直点 <code>Next</code> 即可</p>
</li>
<li class="">
<p>安装完成后，在命令行中进行验证：</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">C:\Users\pc&gt;node -v</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">v12.22.12</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">C:\Users\pc&gt;npm -v</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">6.14.16</span><br></span></code></pre></div></div>
</li>
</ol>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="换源">换源<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E6%8D%A2%E6%BA%90" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h4>
<p>为了加快 npm 下载速度，需要进行换源：</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># 查看当前源</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">npm config get registry</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># 换为中国 npmmirror 镜像源</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">npm config set registry https://registry.npmmirror.com</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># 查看是否换源成功</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">npm config get registry</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="拉取-shenyu-dashboard-代码">拉取 ShenYu Dashboard 代码<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E6%8B%89%E5%8F%96-shenyu-dashboard-%E4%BB%A3%E7%A0%81" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<ol>
<li class="">
<p>Fork <a href="https://github.com/apache/shenyu-dashboard" target="_blank" rel="noopener noreferrer" class="">ShenYu Dashboard</a> 仓库</p>
</li>
<li class="">
<p>使用 Git 下载到本地：</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">git clone git@github.com:${YOUR_USERNAME}/${TARGET_REPO}.git</span><br></span></code></pre></div></div>
</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="前后端联合开发">前后端联合开发<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E5%89%8D%E5%90%8E%E7%AB%AF%E8%81%94%E5%90%88%E5%BC%80%E5%8F%91" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<ol>
<li class="">
<p>在后端仓库 <code>shenyu</code> 的 <code>shenyu-admin/src/main/resources/application.yml</code> 文件中按下图所示添加 <code>enablePrintApiLog: true</code> ，以在后端控制台显示前端接口被调用的日志。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/enable-api-log-b7eedec55079ce1ef7b96e3076f46841.png" width="1356" height="868" class="img_ev3q"></p>
</li>
<li class="">
<p>启动 <code>ShenyuAdminBootstrap</code></p>
</li>
<li class="">
<p>切换至前端仓库 <code>shenyu-dashboard</code> ，打开 <code>README</code> ，依次点击 <code>npm install</code>, <code>npm start</code> 或通过命令行输入上述命令即可通过 <a href="http://localhost:8000/" target="_blank" rel="noopener noreferrer" class="">http://localhost:8000</a> 访问前端界面，并可在后端控制台中显示前端接口被调用的日志，实现前后端联合开发。</p>
<p><img decoding="async" loading="lazy" src="https://shenyu.apache.org/zh/assets/images/admin-log-37289f14905e15906d363c0345b797cb.png" width="1861" height="645" class="img_ev3q"></p>
</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="打包前端代码">打包前端代码<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E6%89%93%E5%8C%85%E5%89%8D%E7%AB%AF%E4%BB%A3%E7%A0%81" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<p>执行 <code>README</code> 中 <code>npm build</code> 命令，并将 dist 文件夹下生成的所有文件复制到后端仓库中 <code>shenyu-admin/src/main/resources/static/</code> 目录下。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为-shenyu-官网做贡献">为 Shenyu 官网做贡献<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E4%B8%BA-shenyu-%E5%AE%98%E7%BD%91%E5%81%9A%E8%B4%A1%E7%8C%AE" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h2>
<p>按照 <a href="https://github.com/apache/shenyu-website" target="_blank" rel="noopener noreferrer" class="">shenyu-website</a> 中 <code>README</code> 进行操作即可。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="小贴士">小贴士<a href="https://shenyu.apache.org/zh/blog/Start-SourceCode-Analysis-Start-Demo-for-Contributor#%E5%B0%8F%E8%B4%B4%E5%A3%AB" class="hash-link" aria-label="Direct link to heading" title="Direct link to heading" translate="no">​</a></h3>
<ol>
<li class="">可以为 <code>yarn</code> 进行换源，流程同 <code>npm</code></li>
<li class="">建议下载 <code>Node</code> <a href="https://nodejs.org/en" target="_blank" rel="noopener noreferrer" class="">官网</a>中 <code>LTS</code> 版本</li>
<li class=""><code>Windows</code> 系统无法进行部署，如需对你的更改进行验证，可以在Linux 虚拟机或服务器上进行部署</li>
</ol>]]></content>
        <author>
            <name>Yuxuan Zhang</name>
            <uri>https://github.com/zuobiao-zhou</uri>
        </author>
        <category label="first-start" term="first-start"/>
        <category label="Apache ShenYu" term="Apache ShenYu"/>
    </entry>
</feed>