<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>小嘉的部落格</title>
  <icon>https://npm.elemecdn.com/nanshen/favicon.ico</icon>
  <subtitle>一个爱折腾的Java开发工程师</subtitle>
  <link href="https://blog.imzjw.cn/atom.xml" rel="self"/>
  
  <link href="https://blog.imzjw.cn/"/>
  <updated>2024-05-15T11:21:15.000Z</updated>
  <id>https://blog.imzjw.cn/</id>
  
  <author>
    <name>GarveyZhong</name>
    <email>admin@imzjw.cn</email>
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Hexo 使用 GitHub Actions 自动提交文章列表到各大搜索引擎</title>
    <link href="https://blog.imzjw.cn/posts/3ed40d11/"/>
    <id>https://blog.imzjw.cn/posts/3ed40d11/</id>
    <published>2024-05-12T09:31:36.000Z</published>
    <updated>2024-05-15T11:21:15.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><p>偶然在逛 Bing 的 <a href="https://www.bing.com/webmasters/home">Webmasters</a> 的时候，发现多了个 <a href="https://www.bing.com/indexnow">IndexNow</a> 原先一直用的 <a href="https://github.com/Lete114/Hexo-SEO-AutoPush">Hexo-SEO-AutoPush</a> 但是有新东西了，和乐特子提了一下，他让我 PR，可惜 JavaScript 不太熟，索性自己用 JAVA 写了个，也顺便学习了 XML 解析器和 XPath 表达式</p><p>项目地址：</p><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/sudojia/hexo-auto-submit-urls"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=sudojia&repo=hexo-auto-submit-urls&show_owner=true"/></a><h2 id="开发思路"><a href="#开发思路" class="headerlink" title="开发思路"></a>开发思路</h2><ol><li><p>获取 RSS 地址</p></li><li><p>进行解析 RSS 并使用 XPath 表达式提取其中的 ID 标签</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 从XML内容中提取id值。</span></span><br><span class="line"><span class="comment"> * 首先解析XML内容，然后使用XPath表达式定位到id元素的文本内容，并将这些内容收集到一个列表中。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> xmlContent 要解析的XML内容，作为字符串提供。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> ids        用于收集提取到的id值的列表。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> Exception 如果解析XML或执行XPath表达式时发生错误，则抛出异常。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">extractIds</span><span class="params">(String xmlContent, List&lt;String&gt; ids)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">    <span class="comment">// 创建一个文档工厂实例，用于构建XML文档解析器</span></span><br><span class="line">    <span class="type">DocumentBuilderFactory</span> <span class="variable">dbf</span> <span class="operator">=</span> DocumentBuilderFactory.newInstance();</span><br><span class="line">    <span class="comment">// 使用文档工厂创建一个文档构建器</span></span><br><span class="line">    <span class="type">DocumentBuilder</span> <span class="variable">db</span> <span class="operator">=</span> dbf.newDocumentBuilder();</span><br><span class="line">    <span class="comment">// 将XML内容解析为DOM文档</span></span><br><span class="line">    <span class="type">Document</span> <span class="variable">doc</span> <span class="operator">=</span> db.parse(<span class="keyword">new</span> <span class="title class_">ByteArrayInputStream</span>(xmlContent.getBytes(StandardCharsets.UTF_8)));</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 创建XPath工厂，用于生成XPath实例</span></span><br><span class="line">    <span class="type">XPathFactory</span> <span class="variable">xPathFactory</span> <span class="operator">=</span> XPathFactory.newInstance();</span><br><span class="line">    <span class="comment">// 创建XPath实例，用于评估XPath表达式</span></span><br><span class="line">    <span class="type">XPath</span> <span class="variable">xpath</span> <span class="operator">=</span> xPathFactory.newXPath();</span><br><span class="line">    <span class="comment">// 编译XPath表达式，用于定位id元素的文本内容</span></span><br><span class="line">    <span class="type">XPathExpression</span> <span class="variable">expr</span> <span class="operator">=</span> xpath.compile(<span class="string">&quot;//feed/entry/id/text()&quot;</span>);</span><br><span class="line">    <span class="comment">// 执行XPath表达式并获取匹配的节点列表</span></span><br><span class="line">    <span class="type">NodeList</span> <span class="variable">nodeList</span> <span class="operator">=</span> (NodeList) expr.evaluate(doc, XPathConstants.NODESET);</span><br><span class="line">    <span class="comment">// 遍历节点列表，将id文本添加到收集列表中</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; nodeList.getLength(); i++) &#123;</span><br><span class="line">        ids.add(nodeList.item(i).getNodeValue());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>最后将这些 ID 循环写入 urls.txt 文件</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 将一串ID写入到指定的文本文件中。</span></span><br><span class="line"><span class="comment"> * 每个ID占一行。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> ids 包含需要写入文件的所有ID的列表。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> IOException 在写入文件过程中发生IO异常。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">writeIdsToFile</span><span class="params">(List&lt;String&gt; ids)</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">    <span class="comment">// 使用BufferedWriter来提高文件写入性能，通过FileWriter指定写入的文件路径</span></span><br><span class="line">    <span class="keyword">try</span> (<span class="type">BufferedWriter</span> <span class="variable">writer</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BufferedWriter</span>(<span class="keyword">new</span> <span class="title class_">FileWriter</span>(TXT_FILE_PATH))) &#123;</span><br><span class="line">        <span class="comment">// 遍历ids列表，将每个ID写入文件，如果ID不是最后一个，则在后面添加换行符</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; ids.size(); i++) &#123;</span><br><span class="line">            <span class="comment">// 写入当前ID</span></span><br><span class="line">            writer.write(ids.get(i));</span><br><span class="line">            <span class="keyword">if</span> (i &lt; ids.size() - <span class="number">1</span>) &#123;</span><br><span class="line">                <span class="comment">// 如果当前ID不是最后一个，则写入换行符</span></span><br><span class="line">                writer.newLine();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>使用并发批量提交 urls.txt 的文本内容到不同的搜索引擎</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 向多个搜索引擎提交URLs。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> host          主机地址</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> siteUrl       网站的URL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> indexNowkey   IndexNow的密钥</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> keyLocation   密钥存储位置</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> bingApiKey    Bing搜索引擎的API密钥</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> baiduApiKey   百度搜索引擎的API密钥</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> googleKey     Google搜索引擎的json文件内容</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> indexNowCount 向IndexNow提交的URL数量</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> bingCount     向Bing提交的URL数量</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> baiDuCount    向百度提交的URL数量</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">submitUrls</span><span class="params">(String host, String siteUrl, String indexNowkey, String keyLocation, String bingApiKey, String baiduApiKey, String googleKey, Integer indexNowCount, Integer bingCount, Integer baiDuCount)</span> &#123;</span><br><span class="line">    List&lt;String&gt; urlList;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 从文件中读取 urls 列表</span></span><br><span class="line">        urlList = ReptileRssTools.readUrlsFromFile();</span><br><span class="line">        <span class="keyword">if</span> (urlList.isEmpty()) &#123;</span><br><span class="line">            <span class="comment">// 如果URL列表为空或读取失败, 取消提交</span></span><br><span class="line">            LOGGER.log(Level.SEVERE, <span class="string">&quot;URL 列表为空或读取 rss 失败, 取消提交！&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        LOGGER.log(Level.SEVERE, <span class="string">&quot;读取 URL 列表时发生异常&quot;</span> + e.getMessage());</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 创建一个固定大小为 5 的线程池，用于并发提交URL到不同的搜索引擎</span></span><br><span class="line">    <span class="type">ExecutorService</span> <span class="variable">executorService</span> <span class="operator">=</span> Executors.newFixedThreadPool(<span class="number">5</span>);</span><br><span class="line">    <span class="comment">// 向IndexNow提交URL任务</span></span><br><span class="line">    executorService.submit(() -&gt; &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            AutoSubmitUrlServiceImpl.pushIndexNowUrl(urlList, host, indexNowkey, keyLocation, indexNowCount);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            LOGGER.log(Level.SEVERE, <span class="string">&quot;提交 URL 到 IndexNow 时发生异常&quot;</span>, e.getMessage());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="comment">// 向Bing提交URL任务</span></span><br><span class="line">    executorService.submit(() -&gt; &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            AutoSubmitUrlServiceImpl.pushBingUrl(urlList, siteUrl, bingApiKey, bingCount);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            LOGGER.log(Level.SEVERE, <span class="string">&quot;提交 URL 到 Bing 时发生异常&quot;</span>, e.getMessage());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="comment">// 向百度提交URL任务</span></span><br><span class="line">    executorService.submit(() -&gt; &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            AutoSubmitUrlServiceImpl.pushBaiduUrl(urlList, siteUrl, baiduApiKey, baiDuCount);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            LOGGER.log(Level.SEVERE, <span class="string">&quot;提交 URL 到 Baidu 时发生异常&quot;</span>, e.getMessage());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="comment">// 向Google提交URL任务</span></span><br><span class="line">    executorService.submit(() -&gt; &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            AutoSubmitUrlServiceImpl.pushGoogleUrl(urlList, googleKey);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            LOGGER.log(Level.SEVERE, <span class="string">&quot;提交 URL 到 Google 时发生异常&quot;</span>, e.getMessage());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="comment">// 关闭线程池，并等待所有任务完成</span></span><br><span class="line">    executorService.shutdown();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 长时间等待所有任务完成，以确保所有提交任务执行完毕</span></span><br><span class="line">        executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">        <span class="comment">// 如果在等待线程池关闭时线程被中断时，尝试恢复中断状态</span></span><br><span class="line">        LOGGER.log(Level.SEVERE, <span class="string">&quot;线程池等待终止时发生异常&quot;</span>, e.getMessage());</span><br><span class="line">        Thread.currentThread().interrupt();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol><h2 id="如何使用"><a href="#如何使用" class="headerlink" title="如何使用"></a>如何使用</h2><ol><li><p>本项目是利用 <code>hexo-generator-feed</code> 生成的 RSS 进行解析并获取文章列表，所以需要你在 Hexo 安装该插件</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-generator-feed --save</span><br></pre></td></tr></table></figure><p>然后在博客的配置文件里添加如下配置</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">feed:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">atom</span></span><br><span class="line">  <span class="attr">path:</span> <span class="string">atom.xml</span></span><br><span class="line">  <span class="attr">limit:</span> <span class="number">0</span></span><br><span class="line">  <span class="attr">hub:</span></span><br><span class="line">  <span class="attr">content:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">content_limit:</span></span><br><span class="line">  <span class="attr">content_limit_delim:</span> <span class="string">&#x27; &#x27;</span></span><br><span class="line">  <span class="attr">order_by:</span> <span class="string">-date</span></span><br><span class="line">  <span class="attr">icon:</span> <span class="string">图标.icon</span></span><br><span class="line">  <span class="attr">autodiscovery:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">template:</span></span><br></pre></td></tr></table></figure><p>详情见插件地址：<a href="https://github.com/hexojs/hexo-generator-feed">hexojs/hexo-generator-feed</a></p></li><li><p>【<a href="https://github.com/sudojia/hexo-auto-submit-urls/fork">Fork</a>】本项目并在仓库的 <code>settings -&gt; Secrets and variables -&gt; Actions -&gt; New repository secret</code> 添加环境变量</p><ul><li>详情见【<a href="https://blog.imzjw.cn/posts/3ed40d11/#%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E">参数说明</a>】</li></ul></li><li><p>最后在 Actions 运行 Workflows 文件</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/3ed40d11/240512-cb12b45fdc64042a.webp" alt="image-20240512181416458"></p></li></ol><h2 id="参数说明"><a href="#参数说明" class="headerlink" title="参数说明"></a>参数说明</h2><table><thead><tr><th align="center">Secrets</th><th align="center">Value 说明</th></tr></thead><tbody><tr><td align="center">RSS_URL</td><td align="center">rss 地址，eg：<code>https://example.org/atom.xml</code></td></tr><tr><td align="center">INDEX_NOW_KEY</td><td align="center"><a href="https://www.bing.com/indexnow/getstarted#implementation">https://www.bing.com/indexnow/getstarted#implementation</a> 获取 KEY 并把文件下载到本地，放在 Hexo 根目录的 source 下<br>eg: 6b0e36ed24d24c68a6f3415c41ee849a</td></tr><tr><td align="center">BING_KEY</td><td align="center"><a href="https://www.bing.com/webmasters/home">https://www.bing.com/webmasters/home</a> 设置 -&gt; API 访问 -&gt; 查看 API 密钥</td></tr><tr><td align="center">BAIDU_KEY</td><td align="center"><a href="https://ziyuan.baidu.com/linksubmit/index">https://ziyuan.baidu.com/linksubmit/index</a> 只要 token 的值</td></tr><tr><td align="center">GOOGLE_KEY</td><td align="center">JSON 内容，到 <a href="https://www.json.cn/jsonzip/">json.cn</a> 压缩代码</td></tr><tr><td align="center">BOT_TOKEN</td><td align="center">通过 <a href="https://t.me/BotFather">@BotFather</a> 获取机器人 token</td></tr><tr><td align="center">CHAT_ID</td><td align="center">和它对话获取 chat_id <a href="https://t.me/userinfobot">@userinfobot</a></td></tr></tbody></table><p><strong>提交数量：</strong></p><p>因本项目是获取你的 RSS 地址，所以你 RSS 有多少条文章链接，就提交多少条，如需要设置提交数量可在 KEY 的后面加个 <code>,</code> 隔开数量</p><div class="note red no-icon flat"><p>注意是英文的逗号，另 GOOGLE_KEY 没有写提交数量，默认就是你的 RSS 文章链接数量</p></div><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">eg: hCvGPEqkx7L5hJur,100</span><br></pre></td></tr></table></figure><p><strong>特别说明：</strong></p><ol><li><p><strong>INDEX_NOW_KEY：</strong>Secrets 变量里不仅需要填入 KEY，还需要你把它那个文件下载并放入到网站的根目录，可以参考官方的请求示例：<code>keyLocation</code></p><figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">POST</span> <span class="string">/IndexNow</span> <span class="meta">HTTP/1.1</span></span><br><span class="line"><span class="attribute">Content-Type</span><span class="punctuation">: </span>application/json; charset=utf-8</span><br><span class="line"><span class="attribute">Host</span><span class="punctuation">: </span>api.indexnow.org</span><br><span class="line">&#123;</span><br><span class="line">  &quot;host&quot;: &quot;www.example.org&quot;,</span><br><span class="line">  &quot;key&quot;: &quot;960ca71a21c141f7a4deb8edcb256bf4&quot;,</span><br><span class="line">  &quot;keyLocation&quot;: &quot;https://www.example.org/960ca71a21c141f7a4deb8edcb256bf4.txt&quot;,</span><br><span class="line">  &quot;urlList&quot;: [</span><br><span class="line">      &quot;https://www.example.org/url1&quot;,</span><br><span class="line">      &quot;https://www.example.org/folder/url2&quot;,</span><br><span class="line">      &quot;https://www.example.org/url3&quot;</span><br><span class="line">      ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p><strong>BAIDU_KEY：</strong>百度提交的好像大部分站长都是 10 条，所以本项目百度提交默认为 10 条，有需求的可以在 token 后加个 <code>,提交的数量</code></p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hCvGPEqkx7L5hJur,100</span><br></pre></td></tr></table></figure></li><li><p><strong>GOOGLE_KEY：</strong>前提你需要创建项目并启用 <code>Web Search Indexing API</code>，最后创建密钥时把 <code>JSON</code> 文件下载到本地，前置操作可以参考【<a href="https://cloud.tencent.com/developer/article/2387384">如何使用google index api来自动提交url</a>】挺详细的。</p><p>然后打开【<a href="https://www.json.cn/jsonzip/">json.cn</a>】压缩 JSON 代码，并填入压缩后的代码</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/3ed40d11/240512-080bdbf5691cc3bf.webp" alt="image-20240512184012784"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/3ed40d11/240512-b314cc46e262151e.webp" alt="image-20240512184140509"></p></li></ol><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>该收录的自然会收录，瞧不上的自然瞧不上 —— 孙泽康</p><p>话虽如此，但是有新东西，我不用，我难受😭</p>]]></content>
    
    
    <summary type="html">偶然在逛 Bing 的 Webmasters 的时候，发现多了个 IndexNow 原先一直用的 Hexo-SEO-AutoPush 但是有新东西了</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>使用 GitHub Actions 自动备份 Twikoo 评论数据</title>
    <link href="https://blog.imzjw.cn/posts/e37cfdac/"/>
    <id>https://blog.imzjw.cn/posts/e37cfdac/</id>
    <published>2024-04-27T01:09:06.000Z</published>
    <updated>2024-05-19T11:25:53.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>也是心血来潮写的这个项目。因为在前面白嫖的 MongoDB 就被停用过，好在备份过一次，不然评论全无了</p><p>项目地址：</p><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/sudojia/comment_backups"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=sudojia&repo=comment_backups&show_owner=true"/></a><div class="note success flat"><p>已优化更新 2024-05-19</p><ol><li>修改 workflows 文件，每隔三天运行，避免资源浪费 <a href="https://github.com/sudojia/comment_backups/commit/10fc7cb674a3ec5542e61a828908079f9b12ab9e">commit#10fc7cb</a></li><li>优化 json 格式，与 twikoo 导出的 json 格式一致 <a href="https://github.com/sudojia/comment_backups/commit/a869f6ab26f08f9bcbfd79a30a6d84aee00127d8">commit#a869f6a</a></li><li>添加写入文件时，文件名带日期格式输出 <a href="https://github.com/sudojia/comment_backups/commit/cbbd174b66a12144861de26c63b0948fdf495b2d">commit#cbbd174</a></li><li>workflows 代码添加删除旧备份文件操作 <a href="https://github.com/sudojia/comment_backups/commit/cbbd174b66a12144861de26c63b0948fdf495b2d">commit#cbbd174</a></li></ol></div><h2 id="使用演示"><a href="#使用演示" class="headerlink" title="使用演示"></a>使用演示</h2><ol><li><p>【<a href="https://github.com/sudojia/comment_backups/fork">fork 项目</a>】</p></li><li><p>在 <code>comment_backups/settings/secrets/actions</code> 填入所需变量</p><table><thead><tr><th align="center">变量名</th><th align="center">值</th></tr></thead><tbody><tr><td align="center">PASSWORD</td><td align="center">Twikoo 密码</td></tr><tr><td align="center">TWIKOO_URL</td><td align="center">你的 Twikoo 地址</td></tr></tbody></table></li><li><p>在 <code>Settings -&gt; Actions -&gt; General</code> 下给到读和写权限</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/e37cfdac/240427-711aab2df03903ad.webp" alt="image-20240427092513810"></p></li><li><p>Run workflow 即可</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/e37cfdac/240427-70c03779d384eb29.webp" alt="image-20240427092332594"></p></li><li><p>如果 Actions 运行时没有出错，那么你的 Twikoo 评论数据就会出现在仓库内了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/e37cfdac/240427-40e0efef3626983e.webp" alt="image-20240427092711991"></p></li><li><p>Actions 每隔三天运行一次，避免没必要的资源浪费！</p></li></ol><h2 id="导入数据"><a href="#导入数据" class="headerlink" title="导入数据"></a>导入数据</h2><div class="note success flat"><p>代码已更新优化，现在直接把仓库里的 <code>twikoo-comment.json</code> 下载到本地之后，到 Twikoo 管理面板导入即可，源系统选择 Twikoo</p></div><p>下面的步骤不用看了</p><ol><li><p>先把仓库里的 <code>twikoo-comment.json</code> 下载到本地，然后去 【<a href="https://www.json.cn/js-format/">Json.cn</a>】进行格式化</p></li><li><p>格式化之后按要求删除</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="deletion">-- &#123;</span></span><br><span class="line"><span class="deletion">--  &quot;code&quot;: 0,</span></span><br><span class="line"><span class="deletion">--  &quot;data&quot;: </span></span><br><span class="line">  [&#123;</span><br><span class="line">      &quot;_id&quot;: &quot;xxx&quot;,</span><br><span class="line">      &quot;nick&quot;: &quot;xxx&quot;,</span><br><span class="line">      &quot;mail&quot;: &quot;xxx@qq.com&quot;,</span><br><span class="line">      &quot;ua&quot;: &quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36&quot;,</span><br><span class="line">      &quot;link&quot;: &quot;xxx&quot;,</span><br><span class="line">      &quot;master&quot;: false,</span><br><span class="line">      &quot;comment&quot;: &quot;xxx&quot;,</span><br><span class="line">      &quot;url&quot;: &quot;/link/&quot;,</span><br><span class="line">      &quot;created&quot;: xxx,</span><br><span class="line">      &quot;updated&quot;: xxxxxx,</span><br><span class="line">      &quot;href&quot;: &quot;https://blog.imzjw.cn/link/&quot;</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      &quot;_id&quot;: &quot;xxx&quot;,</span><br><span class="line">      &quot;uid&quot;: &quot;xxx&quot;,</span><br><span class="line">      &quot;nick&quot;: &quot;xxx&quot;,</span><br><span class="line">      &quot;mail&quot;: &quot;xxx&quot;,</span><br><span class="line">      &quot;mailMd5&quot;: &quot;xxx&quot;,</span><br><span class="line">      &quot;link&quot;: &quot;https://blog.imzjw.cn/&quot;,</span><br><span class="line">      &quot;ua&quot;: &quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36&quot;,</span><br><span class="line">      &quot;ip&quot;: &quot;xxx.xxx.xxx.xxx&quot;,</span><br><span class="line">      &quot;master&quot;: true,</span><br><span class="line">      &quot;url&quot;: &quot;/posts/8f9a47ec/&quot;,</span><br><span class="line">      &quot;href&quot;: &quot;https://blog.imzjw.cn/posts/8f9a47ec/#post-comment&quot;,</span><br><span class="line">      &quot;comment&quot;: &quot;&lt;p&gt;xxx，xxx&lt;/p&gt;\n&quot;,</span><br><span class="line">      &quot;pid&quot;: &quot;xxx&quot;,</span><br><span class="line">      &quot;rid&quot;: &quot;xxx&quot;,</span><br><span class="line">      &quot;isSpam&quot;: xxx,</span><br><span class="line">      &quot;created&quot;: xxx,</span><br><span class="line">      &quot;updated&quot;: xxx</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line"><span class="deletion">--&#125;</span></span><br></pre></td></tr></table></figure><p>完整格式语法如下：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">[</span><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;_id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;xxx&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;nick&quot;</span><span class="punctuation">:</span> <span class="string">&quot;xxx&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;mail&quot;</span><span class="punctuation">:</span> <span class="string">&quot;xxx&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;ua&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;link&quot;</span><span class="punctuation">:</span> <span class="string">&quot;xxx&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;master&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;comment&quot;</span><span class="punctuation">:</span> <span class="string">&quot;xxx&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;url&quot;</span><span class="punctuation">:</span> <span class="string">&quot;/link/&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;created&quot;</span><span class="punctuation">:</span> <span class="number">1602937777006</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;updated&quot;</span><span class="punctuation">:</span> <span class="number">1602937781775</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;href&quot;</span><span class="punctuation">:</span> <span class="string">&quot;https://blog.imzjw.cn/link/&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line"> <span class="punctuation">&#123;</span></span><br><span class="line">     </span><br><span class="line"> <span class="punctuation">&#125;</span>，</span><br><span class="line"> <span class="punctuation">&#123;</span></span><br><span class="line"> </span><br><span class="line"> <span class="punctuation">&#125;</span></span><br><span class="line"> ...</span><br><span class="line"><span class="punctuation">]</span></span><br></pre></td></tr></table></figure></li><li><p>之后即可在 Twikoo 管理面板的导入处进行导入，源系统选择 <code>Twikoo(JSON)</code></p></li></ol>]]></content>
    
    
    <summary type="html">也是心血来潮写的这个项目。因为在前面白嫖的 MongoDB 就被停用过，好在备份过一次，不然评论全无了。项目地址：</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="GitHub Actions" scheme="https://blog.imzjw.cn/tags/GitHub-Actions/"/>
    
    <category term="Twikoo" scheme="https://blog.imzjw.cn/tags/Twikoo/"/>
    
  </entry>
  
  <entry>
    <title>使用 JAVA 写了个 Hexo 静态博客的文章图片备份方法</title>
    <link href="https://blog.imzjw.cn/posts/download-post-img/"/>
    <id>https://blog.imzjw.cn/posts/download-post-img/</id>
    <published>2024-04-23T14:04:48.000Z</published>
    <updated>2024-04-23T14:04:48.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h2><p>我为什么要写这个呢？</p><p>因为目前的图片是 PicGo + GitHub / Alist + Typora 进行上传的，没有存在本地的，虽说图片都在 GitHub 但是本人四个 GitHub 账号都被封了，所以想图个保障就写了这个项目，也防止一些热心人搭建的 jsDelivr 镜像站承受不住压力关站跑路了，然后好巧不巧 GitHub 号也被封了，那这图片就回不来了，总之就是图个保障罢了！</p><p>在此之前也看了一些方法，有浏览器插件的，但是它会把该页面下的所有图片都给 Download 下来，比如赞赏码、相关推荐、以及页脚的图片</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/download-post-img/240423-26ef6b13fceffffb.webp" alt="image-20240423222317686"></p><p>找来找去，没找到适合自己，又不想点击文章一个一个去备份图片，那多累啊，怎么办？那就自己写一个咯</p><p><strong>目前的不足：</strong></p><ol><li>该项目需要 <strong>hexo-seo</strong> 插件的支持，需要它生成 <code>urls.txt</code> 文件</li><li>该项目需要 JDK 环境支持，这个暂时没办法的啦</li></ol><p>有能力的大佬可以用其它的语言再加个前端，在网页上，只要输入 <code>https://blog.xxx.xxx/baidu.txt</code> 爬取该文本内容的所有文章链接进行爬取并打包压缩返回客户端给我下载😁</p><hr><h2 id="项目演示"><a href="#项目演示" class="headerlink" title="项目演示"></a>项目演示</h2><p>项目地址：</p><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/sudojia/reptile_postimg"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=sudojia&repo=reptile_postimg&show_owner=true"/></a><p>首先需要安装 <code>hexo-seo</code> 插件，这个东西装了也没坏处，我用的是乐特子的 <a href="https://github.com/Lete114/hexo-seo-autopush.git">hexo-seo</a> 插件</p><p>然后在博客的根目录添加配置</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># enable: 开启/关闭 推送</span></span><br><span class="line"><span class="comment"># cron: 执行时间周期</span></span><br><span class="line"><span class="comment"># count: 每次提交最新的10篇文章，输入0或者不填写则默认为所有文章(建议是最新的10篇文章)</span></span><br><span class="line"><span class="comment"># date: 更新时间(updated)|创建日期(created)</span></span><br><span class="line"><span class="comment"># https://github.com/Lete114/hexo-seo-autopush.git</span></span><br><span class="line"><span class="attr">hexo_seo_autopush:</span></span><br><span class="line">  <span class="attr">cron:</span> <span class="number">15</span> <span class="number">2</span> <span class="string">*</span> <span class="string">*</span> <span class="string">*</span></span><br><span class="line">  <span class="attr">baidu:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">date:</span> <span class="string">created</span></span><br><span class="line">    <span class="attr">count:</span> <span class="number">200</span></span><br><span class="line">  <span class="attr">bing:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">date:</span> <span class="string">created</span></span><br><span class="line">    <span class="attr">count:</span> <span class="number">300</span></span><br><span class="line">  <span class="attr">google:</span></span><br><span class="line">    <span class="attr">enable:</span> <span class="literal">false</span></span><br><span class="line">    <span class="attr">date:</span> <span class="string">created</span></span><br><span class="line">    <span class="attr">count:</span> <span class="number">10</span></span><br></pre></td></tr></table></figure><p>我百度的这个 200 是为了让它帮我生成最大 200 条文章链接，正常我是 10 的</p><p>然后 <code>hexo cl &amp;&amp; hexo g &amp;&amp; hexo s</code> 就可以在根目录下 <strong>public</strong> 里找到 <strong>baidu.txt</strong> 文件</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/download-post-img/240423-8bcd62948821c4df.webp" alt="image-20240423224647082"></p><p>把这个 <strong>.txt</strong> 文件和这个 <strong>jar</strong> 包放在同一个目录，并重命名为 <strong>urls.txt</strong></p><p>有 JDK 的就直接 <code>java -jar reptile_postimg-1.0.jar 文章目录名</code> 即可</p><ul><li>文章目录名指的是  <code>https://blog.imzjw.cn/posts/b74f504f/</code> 的 <span class="inline-tag red">posts</span>，因为每个人都不可能是 <strong>posts</strong></li></ul><p>没有的话就只能下载安装了</p><div class="btns rounded grid5">            <a class="button" href='https://repo.huaweicloud.com/java/jdk/8u202-b08/jdk-8u202-windows-x64.exe' title='华为云镜像下载'><i class='fas fa-download'></i>华为云镜像下载</a>          </div><p>安装就直接下一步下一步，然后配置<a href="https://blog.csdn.net/m0_63615119/article/details/132558887">环境变量</a></p><p>配置好之后，CMD 进入项目</p><p>输入命令：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -jar reptile_postimg-1.0.jar posts</span><br></pre></td></tr></table></figure><p>目前就测试了五条链接，基本没什么问题，会以你的文章 ID 命名创建文件夹并存放对应的文章图片！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/download-post-img/240423-70ffec8fc6461238.webp" alt="image-20240423235811353"></p><p>仅支持 <code>https://blog.xxx.com/xxx/abcd/ 和 /xxx/abcd.html</code> 格式</p><p>如果该文章下没有图片的话，它会返回该文章下没有图片！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/download-post-img/240424-16419d6917cfc785.webp" alt="image-20240424001013682"></p><div class="note danger flat"><p>另外也不建议，一下就 100 条，200 条，IO 可能会抛异常！</p></div>]]></content>
    
    
    <summary type="html">我为什么要写这个呢？因为目前的图片是 PicGo + GitHub / Alist + Typora 进行上传的，没有存在本地的，虽说图片都在 GitHub 但是本人四个 GitHub 账号都被封了，所以想图个保障就写了这个项目.</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>重新整理部落格分类</title>
    <link href="https://blog.imzjw.cn/posts/88c14d33/"/>
    <id>https://blog.imzjw.cn/posts/88c14d33/</id>
    <published>2024-04-22T10:19:33.000Z</published>
    <updated>2024-04-22T10:19:33.000Z</updated>
    
    <content type="html"><![CDATA[<p>在今天下午，我把我部落格分类重新整理了个遍</p><p>原分类：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/88c14d33/240422-a59c133159018b97.webp" alt="image-20240422183346865"></p><p>又臭又长！</p><p>整理后的分类：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/88c14d33/240422-3f9d33e6696cca9c.webp" alt="image-20240422183414297"></p><p>干净简洁！</p><p>分类说明：</p><ul><li><strong>Develop</strong>：放一些关于后端的、前端的、Linux，总之有关开发的都放在这了</li><li><strong>Hexo</strong>：见其字如知其意</li><li><strong>实用分享</strong>：分享一些实用的工具、网站、好玩的东西等</li><li><strong>经验分享</strong>：记录自己踩下的坑</li><li><strong>闲聊杂话</strong>：瞎扯，比如这篇文章😁</li></ul>]]></content>
    
    
    <summary type="html">在今天下午，我把我部落格分类重新整理了个遍，原分类又臭又长，整理后的分类干净整洁</summary>
    
    
    
    <category term="闲聊杂话" scheme="https://blog.imzjw.cn/categories/%E9%97%B2%E8%81%8A%E6%9D%82%E8%AF%9D/"/>
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>解决网站 URL 加个 index.html 后 Twikoo 评论不显示问题</title>
    <link href="https://blog.imzjw.cn/posts/51a5d1ca/"/>
    <id>https://blog.imzjw.cn/posts/51a5d1ca/</id>
    <published>2024-04-22T07:45:11.000Z</published>
    <updated>2024-04-22T07:45:11.000Z</updated>
    
    <content type="html"><![CDATA[<p>其实这问题也是最开始的时候用 <code>hexo-abbrlink</code> 规则没配置好，导致它可以在后面加个 <strong>index.html</strong></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/51a5d1ca/240422-21830a3e04f6f401.webp" alt="image-20240422155420310"></p><p>这种规则的话，它是可以在后面加个 <strong>index.html</strong> 的</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/51a5d1ca/240422-e86c645986191f8f.webp" alt="image-20240422155648132"></p><p>那这样的话就是两个页面了，所以在 <code>/posts/b74f504f/</code> 页面的评论在 <code>/posts/b74f504f/index.html</code> 是看不到的。</p><h2 id="解决措施"><a href="#解决措施" class="headerlink" title="解决措施"></a>解决措施</h2><p>你可以用 Navicat Premium 15 登录 MongoDB 进行修改，吧所有后面带 index.html 的删了。<psw>嘿嘿，开个玩笑</psw></p><p>在 Twikoo 初始函数的时候添加 <code>location.pathname.replace(/index\.html$/, &#39;&#39;),</code></p><p>Butterfly 主题可以在 <code>themes\butterfly\layout\includes\third-party\comments\twikoo.pug</code> 进行修改，其它主题的话，就找到这段代码加上就好了</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">const init = () =&gt; &#123;</span><br><span class="line">      twikoo.init(Object.assign(&#123;</span><br><span class="line">        el: &#x27;#twikoo-wrap&#x27;,</span><br><span class="line">        envId: &#x27;!&#123;envId&#125;&#x27;,</span><br><span class="line"><span class="addition">+        path: location.pathname.replace(/index\.html$/, &#x27;&#x27;),</span></span><br><span class="line">        region: &#x27;!&#123;region&#125;&#x27;,</span><br><span class="line">        onCommentLoaded: () =&gt; &#123;</span><br><span class="line">          btf.loadLightbox(document.querySelectorAll(&#x27;#twikoo .tk-content img:not(.tk-owo-emotion)&#x27;))</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;, !&#123;JSON.stringify(option)&#125;))</span><br></pre></td></tr></table></figure><p>现在不管怎么请求 <strong>index.html</strong>，他请求的数据都是没有带 <strong>index.html</strong> 的了，响应回来的数据也是一样的了。</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/51a5d1ca/240422-3ade940cf6cb6796.webp" alt="image-20240422162918881" style="zoom:50%;" /><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>新站的话链接规则改成 <code>posts/:abbrlink.html</code> 就没这个问题了，老站还是不要改了。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/51a5d1ca/240422-3c0a232d2c336dcd.webp" alt="image-20240422163317952"></p><p>参考</p><ul><li><a href="https://github.com/twikoojs/twikoo/issues/608">issues</a></li></ul>]]></content>
    
    
    <summary type="html">其实这问题也是最开始的时候用 hexo-abbrlink，规则没配置好，导致它可以在后面加个 index.html，这种规则的话，它是可以在后面加个 index.html 的</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/tags/Hexo/"/>
    
    <category term="Twikoo" scheme="https://blog.imzjw.cn/tags/Twikoo/"/>
    
  </entry>
  
  <entry>
    <title>分享几个免费使用 GPT-4、GPT-4 Turbo、DALL-E 3 等大模型 AI</title>
    <link href="https://blog.imzjw.cn/posts/ff838eeb/"/>
    <id>https://blog.imzjw.cn/posts/ff838eeb/</id>
    <published>2024-04-21T07:35:06.000Z</published>
    <updated>2024-04-21T07:35:06.000Z</updated>
    
    <content type="html"><![CDATA[<p>2024 年都快过去一半了，还是有一些铁子，因为付费的问题，没能用到最新的 GPT - 4 模型，所以分享几个免费使用 Chat GPT4.0 大模型的 AI 机器人，以下都是没有次数限制的，想用多久就用多久，从此告别 Chat GPT Plus 每月 20 美金的费用！</p><h2 id="COZE"><a href="#COZE" class="headerlink" title="COZE"></a>COZE</h2><p>俗称扣子，据介绍，Coze 扣子支持 30 秒无代码生成 AI Bot，集成了超过 60 种不同的插件，覆盖新闻阅读、旅行规划、生产力工具等多个领域，用户可以根据需求快速为机器人添加功能。同时，扣子还支持一键分享至微信、飞书等社交平台，让更多人使用到自己创建的 Chatbot，更重要的是，它是<strong>字节跳动</strong>推出的 AI 聊天机器人开发平台，有些人可能还不清楚，抖音、TikTok，今日头条等，都是字节跳动的。</p><p>首先，打开官网：<a href="https://www.coze.com/">Coze</a> ，右上角 Get started 注册，有两种注册方式，可以选择手机号注册，有谷歌账号的建议谷歌一键注册的，比较方便，然后鼠标右击按 <kbd>T</kbd> 即可翻译中文</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/ff838eeb/240421-f137906942e23181.webp" alt="image-20240421162655840"></p><p>点击左上角创建机器人</p><ol><li>工作空间选择个人</li><li>机器人名称</li><li>描述，随意填写</li><li>机器人头像，自定义上传头像或者默认即可</li></ol><p>最后点击确认！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/ff838eeb/240421-5cafe78dce2adb14.webp" alt="image-20240421163117730"></p><p>创建好之后，更改 GPT 模型，默认是 8 k，我们将其改成 GPT - 4 Turbo（128k）性能会更强！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/ff838eeb/240421-242117364f8752ac.webp" alt="image-20240421163511394"></p><p>然后我们选择 Plugins 里的 <kbd>+</kbd> 号，即 <code>Add plugin</code> 添加一些插件</p><p>以下列举几个我用的插件，其它的插件，大家可根据情况去选择</p><ol><li><strong>GPT4V</strong>：通过自动分析图像内容并将其转换为描述性文本来进行高级图像识别。也就是图像转文本</li><li><strong>DALLE 3</strong>：也就是通过文字描述来创建图片</li><li><strong>Data Analysis</strong>：数据分析</li><li><strong>CapCut</strong>：文生视频，通过文字描述来创建视频</li><li><strong>Code Interpreter</strong>：代码解释器</li><li><strong>Doc Maker</strong>：文档生成器</li><li><strong>bilibili</strong>：哔哔哩哩插件，可以获取热门视频</li><li><strong>Generate MindMap</strong>：根据文字内容制作思维导图图片</li></ol><p>装好之后，建议打开长期记忆功能，就是上下文的记忆</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/ff838eeb/240421-ce9acdefbe3eed62.webp" alt="image-20240421164852319"></p><p>最后我们可以测试一下</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/ff838eeb/240421-5f48ae9d37e49c2d.webp" alt="image-20240421171211031"></p><p>扣子的功能远不于此，还可以分析文件，TikTok 广告脚本，营销文案等，更多进阶功能可以 Google 查看教程</p><h2 id="Claude-3"><a href="#Claude-3" class="headerlink" title="Claude 3"></a>Claude 3</h2><p>就像是 AI 界的黑马，打的其它对手措不及防，通过最新的模型性能基准测试，我们可以发现，<code>Claude 3</code> 的最强版本，已经可以完全碾压 GPT - 4，Google Gemini Ultra 等主流大模型，Claude 是一家新兴的 AI 创业公司，谷歌也在上面进行了巨额投资，目前性能跟 ChatGPT - 4 不相上下，它在上下文对话能力，写作、写文案、写代码、解释概念、翻译等方面都表现的相当出色！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/ff838eeb/240421-88b7580ea2b66859.webp" alt="image-20240421171715104"></p><p>官网：<a href="https://claude.ai/">Claude</a> </p><p>注册需要 Claude 支持国家，详情见【<a href="https://support.anthropic.com/zh-CN/articles/8461763-%E6%88%91%E5%9C%A8%E5%93%AA%E9%87%8C%E5%8F%AF%E4%BB%A5%E8%AE%BF%E9%97%AEclaude-ai">我在哪里可以访问Claude.ai?</a>】并切换到对应的  <strong><emp>Note</emp></strong></p><p>有谷歌账号的建议使用谷歌一键注册，比较方便</p><p>接下来到了手机号验证</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/ff838eeb/240421-aa38a78f9b21e8b6.webp" alt="image-20240421174901325"></p><p>验证完之后，就会让你输入一个昵称，最后点击确认并继续</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/ff838eeb/240421-eb4acfe8f8b23027.webp" alt="image-20240421175010765"></p><p>使用：</p><p>通过一张截图，就可以帮我们实现代码</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/ff838eeb/240421-80121ff31e87993d.webp" alt="image-20240421180442025"></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line">import React from &#x27;react&#x27;;</span><br><span class="line"></span><br><span class="line">const GitHubSignIn = () =&gt; &#123;</span><br><span class="line">  return (</span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&quot;flex flex-col items-center justify-center min-h-screen bg-gray-100&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&quot;w-full max-w-md px-6 py-8 bg-white rounded-lg shadow-md&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&quot;flex justify-center mb-6&quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;/github-logo.png&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;GitHub Logo&quot;</span> <span class="attr">className</span>=<span class="string">&quot;h-12&quot;</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">h1</span> <span class="attr">className</span>=<span class="string">&quot;text-3xl font-bold text-center mb-8&quot;</span>&gt;</span>Sign in to GitHub<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&quot;mb-4&quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">input</span></span></span><br><span class="line"><span class="tag">            <span class="attr">type</span>=<span class="string">&quot;text&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">placeholder</span>=<span class="string">&quot;Username or email address&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">className</span>=<span class="string">&quot;w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500&quot;</span></span></span><br><span class="line"><span class="tag">          /&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&quot;mb-6&quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">input</span></span></span><br><span class="line"><span class="tag">            <span class="attr">type</span>=<span class="string">&quot;password&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">placeholder</span>=<span class="string">&quot;Password&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">className</span>=<span class="string">&quot;w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500&quot;</span></span></span><br><span class="line"><span class="tag">          /&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span> <span class="attr">className</span>=<span class="string">&quot;text-sm text-blue-500 hover:text-blue-700 mt-2 block&quot;</span>&gt;</span></span><br><span class="line">            Forgot password?</span><br><span class="line">          <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">className</span>=<span class="string">&quot;w-full py-2 px-4 bg-green-500 text-white font-semibold rounded-md hover:bg-green-600 mb-4&quot;</span>&gt;</span></span><br><span class="line">          Sign in</span><br><span class="line">        <span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&quot;flex justify-center mb-4&quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">span</span> <span class="attr">className</span>=<span class="string">&quot;text-gray-500&quot;</span>&gt;</span>or<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">className</span>=<span class="string">&quot;w-full py-2 px-4 border border-gray-300 rounded-md hover:bg-gray-100&quot;</span>&gt;</span></span><br><span class="line">          Sign in with a passkey</span><br><span class="line">        <span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&quot;text-center mt-6&quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span> <span class="attr">className</span>=<span class="string">&quot;text-sm text-blue-500 hover:text-blue-700&quot;</span>&gt;</span></span><br><span class="line">            New to GitHub? Create an account</span><br><span class="line">          <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&quot;text-sm text-gray-500 mt-4&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span> <span class="attr">className</span>=<span class="string">&quot;mr-2 hover:text-gray-700&quot;</span>&gt;</span></span><br><span class="line">          Terms</span><br><span class="line">        <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span> <span class="attr">className</span>=<span class="string">&quot;mr-2 hover:text-gray-700&quot;</span>&gt;</span></span><br><span class="line">          Privacy</span><br><span class="line">        <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span> <span class="attr">className</span>=<span class="string">&quot;mr-2 hover:text-gray-700&quot;</span>&gt;</span></span><br><span class="line">          Docs</span><br><span class="line">        <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span> <span class="attr">className</span>=<span class="string">&quot;mr-2 hover:text-gray-700&quot;</span>&gt;</span></span><br><span class="line">          Contact GitHub Support</span><br><span class="line">        <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span> <span class="attr">className</span>=<span class="string">&quot;mr-2 hover:text-gray-700&quot;</span>&gt;</span></span><br><span class="line">          Manage cookies</span><br><span class="line">        <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span> <span class="attr">className</span>=<span class="string">&quot;hover:text-gray-700&quot;</span>&gt;</span></span><br><span class="line">          Do not share my personal information</span><br><span class="line">        <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  );</span><br><span class="line">&#125;;</span><br><span class="line">export default GitHubSignIn;</span><br></pre></td></tr></table></figure><p>也可以发送 PDF、World 等文档让 Claude 分析</p><p>具体功能大家可以自己去尝试</p><h2 id="Kimi"><a href="#Kimi" class="headerlink" title="Kimi"></a>Kimi</h2><p>官网：<a href="https://kimi.moonshot.cn/">Kimi</a></p><p>独立的 AI 助手，国产大语言模型，在上下文记忆能力很有特色，不限次数，完全免费</p><p>一般写代码，SQL 语句我会找他，太方便了，具体功能大家可以自己去尝试，或者可以参考少数派专门为 Kimi 写了篇文章<a class="btn-beautify blue" href="https://sspai.com/post/85687"   title="传送门"><i class="far fa-hand-point-right"></i><span>传送门</span></a></p><h2 id="Copilot"><a href="#Copilot" class="headerlink" title="Copilot"></a>Copilot</h2><p>Windows 11 自带，手机端可以去 <a href="https://play.google.com/store/search?q=copilot&c=apps&hl=zh-HK">Play 商店</a>下载，安装完后打开 GPT4</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/ff838eeb/240421-39443c016770b8a9.webp" alt="image-20240421184601842"></p><h2 id="其它"><a href="#其它" class="headerlink" title="其它"></a>其它</h2><ul><li><p><em>Taskade</em></p></li><li><p>套壳网站，有些网站为了自身的推广也会支持 GPT4 或者其它大语言模型，譬如 Gnomic，就是套壳网站，简单接入了不同主流的大语言模型 API 提供 AI 对话功能</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/ycubaby/ycu-assets/p/ff838eeb/240421-27d40c476f10a10b.webp" alt="image-20240421182810604"></p></li></ul>]]></content>
    
    
    <summary type="html">2024 年都快过去一半了，还是有一些铁子，因为付费的问题，没能用到最新的 GPT - 4 模型，所以分享几个免费使用 ChatGPT4.0 大模型的 AI 机器人</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="人工智能" scheme="https://blog.imzjw.cn/tags/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/"/>
    
  </entry>
  
  <entry>
    <title>Hexo 使用 GitHub Actions 部署后自动刷新多吉云缓存</title>
    <link href="https://blog.imzjw.cn/posts/4ac1b6b1/"/>
    <id>https://blog.imzjw.cn/posts/4ac1b6b1/</id>
    <published>2024-04-19T09:06:08.000Z</published>
    <updated>2024-04-19T09:06:08.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><p>可喜可贺，多吉云终于有刷新预热的接口了，还记得 21 年的时候，当时我还问过客服，刷新预热有没有接口可以调用？不然每次更新部落格的时候，都要手动通过多吉云控制台刷新部落格的缓存，然而客服回的没有，印象中好像是说后面再完善，在博主消失了两年后，多吉云终于有接口啦！</p><p>OK，话不多说</p><p>前提要求：</p><p>Hexo 是通过 GitHub Actions 自动部署的，如果还没使用到 GitHub Actions 自动部署的可以看下站内 <a href="https://blog.imzjw.cn/posts/df27ccfb/">GitHub Actions 自动部署 Hexo</a>，也可以 Google 看看教程</p><h2 id="创建-yml-文件"><a href="#创建-yml-文件" class="headerlink" title="创建 yml 文件"></a>创建 yml 文件</h2><p>在 <code>BlogRoot/.github/workflows</code> 目录下新建 <code>refresh-dogecloud.yml</code></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># This workflow will install Python dependencies, run tests and lint with a single version of Python</span></span><br><span class="line"><span class="comment"># For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python</span></span><br><span class="line"></span><br><span class="line"><span class="attr">name:</span> <span class="string">Refresh</span> <span class="string">DogeCloud</span> <span class="string">CDN</span></span><br><span class="line"></span><br><span class="line"><span class="attr">on:</span></span><br><span class="line">  <span class="attr">push:</span></span><br><span class="line">    <span class="attr">branches:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">master</span> <span class="comment"># 注意改成你的分支</span></span><br><span class="line">  <span class="attr">workflow_dispatch:</span></span><br><span class="line"></span><br><span class="line"><span class="attr">jobs:</span></span><br><span class="line">  <span class="attr">build:</span></span><br><span class="line">    <span class="attr">runs-on:</span> <span class="string">ubuntu-latest</span></span><br><span class="line">    <span class="attr">steps:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">uses:</span> <span class="string">actions/checkout@v3</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">uses:</span> <span class="string">szenius/set-timezone@v1.0</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">timezoneLinux:</span> <span class="string">&quot;Asia/Shanghai&quot;</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Set</span> <span class="string">up</span> <span class="string">Python</span> <span class="number">3.10</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">actions/setup-python@v3</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">python-version:</span> <span class="string">&quot;3.10&quot;</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Wait</span> <span class="string">for</span> <span class="number">2</span> <span class="string">minutes</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">sleep</span> <span class="number">120</span> <span class="comment"># 等待 2 分钟，单位为秒</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Run</span> <span class="string">refresh</span> <span class="string">script</span></span><br><span class="line">        <span class="attr">env:</span></span><br><span class="line">            <span class="attr">ACCESS_KEY:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.ACCESS_KEY</span> <span class="string">&#125;&#125;</span></span><br><span class="line">            <span class="attr">SECRET_KEY:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.SECRET_KEY</span> <span class="string">&#125;&#125;</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">          pip install requests</span></span><br><span class="line"><span class="string">          python refresh-dogecloud.py</span></span><br></pre></td></tr></table></figure><p>上面的等待意思是，等 GitHub Actions 部署好博客的静态资源后再执行刷新多吉云缓存，怎么看自己需要多少分钟呢？</p><p>打开你博客源码 GitHub Actions，查看到部署花费的时间，可以看到我的基本都是在一分半左右，此时，我的 <code>refresh-dogecloud.yml</code> 里就是等待两分钟，注意是<strong>秒</strong>为单位，<code>2 * 60 = 120</code>，所以我的就是 120 秒。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/npm/yc-pic@1.0.3/p/4ac1b6b1/20240419172425.webp" alt="20240419172425"></p><h2 id="创建-PY-脚本"><a href="#创建-PY-脚本" class="headerlink" title="创建 PY 脚本"></a>创建 PY 脚本</h2><p>接下来创建一个脚本来调用多吉云接口。</p><p>在博客的根目录下创建 <code>refresh-dogecloud.py</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> hashlib <span class="keyword">import</span> sha1</span><br><span class="line"><span class="keyword">import</span> hmac</span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"><span class="keyword">import</span> urllib</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">dogecloud_api</span>(<span class="params">api_path, data=&#123;&#125;, json_mode=<span class="literal">False</span></span>):</span><br><span class="line">    access_key = os.environ[<span class="string">&quot;ACCESS_KEY&quot;</span>]</span><br><span class="line">    secret_key = os.environ[<span class="string">&quot;SECRET_KEY&quot;</span>]</span><br><span class="line">    body = <span class="string">&#x27;&#x27;</span></span><br><span class="line">    mime = <span class="string">&#x27;&#x27;</span></span><br><span class="line">    <span class="keyword">if</span> json_mode:</span><br><span class="line">        body = json.dumps(data)</span><br><span class="line">        mime = <span class="string">&#x27;application/json&#x27;</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        body = urllib.parse.urlencode(data) <span class="comment"># Python 2 可以直接用 urllib.urlencode</span></span><br><span class="line">        mime = <span class="string">&#x27;application/x-www-form-urlencoded&#x27;</span></span><br><span class="line">    sign_str = api_path + <span class="string">&quot;\n&quot;</span> + body</span><br><span class="line">    signed_data = hmac.new(secret_key.encode(<span class="string">&#x27;utf-8&#x27;</span>), sign_str.encode(<span class="string">&#x27;utf-8&#x27;</span>), sha1)</span><br><span class="line">    sign = signed_data.digest().<span class="built_in">hex</span>()</span><br><span class="line">    authorization = <span class="string">&#x27;TOKEN &#x27;</span> + access_key + <span class="string">&#x27;:&#x27;</span> + sign</span><br><span class="line">    response = requests.post(<span class="string">&#x27;https://api.dogecloud.com&#x27;</span> + api_path, data=body, headers = &#123;</span><br><span class="line">        <span class="string">&#x27;Authorization&#x27;</span>: authorization,</span><br><span class="line">        <span class="string">&#x27;Content-Type&#x27;</span>: mime</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">return</span> response.json()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">url_list = [</span><br><span class="line">    <span class="string">&quot;https://blog.imzjw.cn/&quot;</span>,</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line">api = dogecloud_api(<span class="string">&#x27;/cdn/refresh/add.json&#x27;</span>, &#123;</span><br><span class="line">    <span class="string">&#x27;rtype&#x27;</span>: <span class="string">&#x27;path&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;urls&#x27;</span>: json.dumps(url_list)</span><br><span class="line">&#125;)</span><br><span class="line"><span class="keyword">if</span> api[<span class="string">&#x27;code&#x27;</span>] == <span class="number">200</span>:</span><br><span class="line">    <span class="built_in">print</span>(api[<span class="string">&#x27;data&#x27;</span>][<span class="string">&#x27;task_id&#x27;</span>])</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&quot;api failed: &quot;</span> + api[<span class="string">&#x27;msg&#x27;</span>]) <span class="comment"># 失败</span></span><br></pre></td></tr></table></figure><p>这段代码采用的是目录刷新的接口，如果你想调用 URL 刷新接口也很简单</p><p>只要把 <code>path</code> 改成 <code>url</code> 即可</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">api = dogecloud_api(<span class="string">&#x27;/cdn/refresh/add.json&#x27;</span>, &#123;</span><br><span class="line">    <span class="string">&#x27;rtype&#x27;</span>: <span class="string">&#x27;url&#x27;</span>, <span class="comment"># &lt;--- URL 刷新</span></span><br><span class="line">    <span class="string">&#x27;urls&#x27;</span>: json.dumps(url_list)</span><br><span class="line">&#125;)</span><br><span class="line"><span class="keyword">if</span> api[<span class="string">&#x27;code&#x27;</span>] == <span class="number">200</span>:</span><br><span class="line">    <span class="built_in">print</span>(api[<span class="string">&#x27;data&#x27;</span>][<span class="string">&#x27;task_id&#x27;</span>])</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&quot;api failed: &quot;</span> + api[<span class="string">&#x27;msg&#x27;</span>]) <span class="comment"># 失败</span></span><br></pre></td></tr></table></figure><p>最后记得修改 <code>url_list</code> 里的链接，该 <code>url_list</code> 是个数组集合，也就是说它可以包含多个链接。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">url_list = [</span><br><span class="line">    <span class="string">&quot;https://blog.imzjw.cn/&quot;</span>,</span><br><span class="line">    <span class="string">&quot;https://blog.imzjw.cn/doge.json&quot;</span>,</span><br><span class="line">    <span class="string">&quot;https://cdn.imzjw.cn/&quot;</span>,</span><br><span class="line">]</span><br></pre></td></tr></table></figure><h2 id="新增-Secrets-变量"><a href="#新增-Secrets-变量" class="headerlink" title="新增 Secrets 变量"></a>新增 Secrets 变量</h2><ol><li><p>在<a href="https://console.dogecloud.com/user/keys">多吉云用户中心 - 密钥管理</a> 获取 <code>ACCESS_KEY</code> 、<code>SECRET_KEY</code></p></li><li><p>在 GitHub 仓库 <code>settings -&gt; Secrets and variables -&gt; Actions</code> 里添加 <code>ACCESS_KEY</code> 、<code>SECRET_KEY</code> 变量</p></li><li><p>避免因权限问题导致工作流执行失败，可以设置下 Actions 读写权限</p><p>懒得截图了，直接借用 <a href="https://blog.cpen.top/">@Mycpen</a> 的图</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/npm/yc-pic@1.0.3/p/4ac1b6b1/20240419174251.webp" alt="20240419174251"></p></li><li><p>最后 <code>git push</code> 即可</p></li></ol><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>本文参考了 <a href="https://blog.cpen.top/posts/6f7759e0.html">Hexo-GitHub Actions 自动刷新多吉云 CDN 缓存</a> 并做了一些教程改动。</p><p>其它：</p><ul><li><a href="https://docs.dogecloud.com/cdn/sdk-full-python?id=%E5%88%B7%E6%96%B0%E9%A2%84%E7%83%AD">多吉云：刷新预热</a></li></ul>]]></content>
    
    
    <summary type="html">可喜可贺，多吉云终于有刷新预热的接口了，还记得 21 年的时候，当时我还问过客服，刷新预热有没有接口可以调用？不然每次更新部落格的时候，都要手动通过多吉云控制台刷新部落格的缓存</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="多吉云" scheme="https://blog.imzjw.cn/tags/%E5%A4%9A%E5%90%89%E4%BA%91/"/>
    
  </entry>
  
  <entry>
    <title>折腾了三天，终于解决了使用多吉云首页打不开问题</title>
    <link href="https://blog.imzjw.cn/posts/dd790023/"/>
    <id>https://blog.imzjw.cn/posts/dd790023/</id>
    <published>2024-04-19T05:44:26.000Z</published>
    <updated>2024-04-19T05:44:26.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="起因"><a href="#起因" class="headerlink" title="起因"></a>起因</h2><p>在使用多吉云的时候，打开我的部落格是这样的</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/npm/yc-pic@1.0.2/p/dd790023/20240419135139.webp" alt="20240419135139" style="zoom: 33%;" /><p>这让我百思不得其解，打开控制台，发现是这个 CSS 加载不了</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/npm/yc-pic@1.0.2/p/dd790023/20240419135512.webp" alt="20240419135512" style="zoom: 67%;" /><p>当我打开了 Proxy 去访问，结果又能访问到，所以一开始我的猜测就是会不会这个 CSS 没走多吉呢，而是走的 GitHub 直连。</p><p>然后就问了客服</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/npm/yc-pic@1.0.2/p/dd790023/20240419135853.webp" alt="20240419135853" style="zoom: 50%;" /><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/npm/yc-pic@1.0.2/p/dd790023/20240419135919.webp" alt="20240419135919" style="zoom:50%;" /><p>客服就建议我在 CSS 后缀里面加个版本号试试，首页确实是可以打开，但是并没什么用，我其它的 XML，JS 等，反正就是我博客根目录的文件全被屏蔽了</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/npm/yc-pic@1.0.2/p/dd790023/20240419140026.webp" alt="20240419140026" style="zoom: 50%;" /><p>后面问了 <a href="https://hin.cool/">@瓦解哥</a> 也是无解，最后换了个大胆的想法，就是会不会是 CDN 访问不了 GitHub 才导致的？</p><p>紧接着联想到 <a href="https://vercel.app/">Vercel</a> 有国内的 CNAME：<code>cname-china.vercel.com</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/npm/yc-pic@1.0.2/p/dd790023/20240419141808.webp" alt="20240419141808"></p><p>最后才因此解决这个鬼问题！</p><p>心累，刚回来折腾一下部落格就碰到这个鬼问题！</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>就是因为 GitHub 被墙了，多吉的 CDN 回源的过程中产生超时！</p>]]></content>
    
    
    <summary type="html">起因在使用多吉云的时候，打开我的部落格是这样的，这让我百思不得其解，打开控制台，发现是这个 CSS 加载不了，当我打开了 Proxy 去访问，结果又能访问到，所以一开始我的猜测就是会不会这个 CSS 没走多吉呢，而是走的 GitHub 直连。</summary>
    
    
    
    <category term="经验分享" scheme="https://blog.imzjw.cn/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="多吉云" scheme="https://blog.imzjw.cn/tags/%E5%A4%9A%E5%90%89%E4%BA%91/"/>
    
  </entry>
  
  <entry>
    <title>Hexo 升级食用指南</title>
    <link href="https://blog.imzjw.cn/posts/26ba0825/"/>
    <id>https://blog.imzjw.cn/posts/26ba0825/</id>
    <published>2024-04-14T09:00:02.000Z</published>
    <updated>2024-04-14T09:00:02.000Z</updated>
    
    <content type="html"><![CDATA[<p>已经有两年没折腾部落格了，不禁感慨，时间过得是真快。</p><p>这几天没事做，捣鼓捣鼓，发现好多插件版本都太低了，Hexo 版本我还是 v4 版本😂，Butterfly 也要升级，这想必就是静态博客所带来的烦恼吧，借此记录一下，万一后面又消失几年，此篇文章就可以派上用场了！</p><h2 id="Node-升级"><a href="#Node-升级" class="headerlink" title="Node 升级"></a>Node 升级</h2><p>这个灰常简单，去<a href="https://nodejs.org/">官网</a>，或者<a href="https://nodejs.cn/">中文网</a> <a class="btn-beautify pink" href="https://npmmirror.com/mirrors/node/v18.20.0/node-v18.20.0-x64.msi"   title="下载 18.20.0 版本"><i class="far fa-hand-point-right"></i><span>下载 18.20.0 版本</span></a></p><h2 id="Hexo-升级"><a href="#Hexo-升级" class="headerlink" title="Hexo 升级"></a>Hexo 升级</h2><ol><li><p>全局升级 <code>hexo-cli</code>，先 <code>hexo version</code> 查看当前版本，然后 <code>npm install -g hexo-cli</code>，再次 <code>hexo version</code> 查看是否升级成功。</p></li><li><p>进入博客根目录，输入如下代码，安装使用检查博客安装的插件是否有升级的</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install -g npm-check</span><br><span class="line">npm-check</span><br></pre></td></tr></table></figure></li><li><p>输入如下代码，安装使用升级相关插件</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">npm install -g npm-upgrade</span><br><span class="line">npm-upgrade</span><br><span class="line">npm update -g</span><br><span class="line"></span><br><span class="line"><span class="comment"># 他会询问你这个插件要升级还是不升级还是忽略?</span></span><br><span class="line"><span class="comment"># 选 y 就会自动吧你的 package.json 里的版本号给替换掉最新版本</span></span><br></pre></td></tr></table></figure></li><li><p>最后 <code>npm install</code> 安装最新版本插件</p></li></ol><h2 id="Butterfly-升级"><a href="#Butterfly-升级" class="headerlink" title="Butterfly 升级"></a>Butterfly 升级</h2><p>直接 <code>git pull</code> 然后参考主题文档配置 <code>_config.butterfly.yml</code></p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>经过如上这些，你的博客也基本差不多就像翻新的一样了！</p><p>最后，折腾的这几天，个人感觉，一个博客，还是简单、简约大气为好，最主要的还是博客里的内容</p><p>当初不知怎么的，就看上了 Butterfly，搞的贼花里胡哨，后悔了，加载也慢，以至于现在只能删删减减一些 <code>CSS/JS</code></p><p>要是能重来，我必选</p><div class="tag link"><a class="link-card" title="hexo-theme-oranges" href="https://github.com/zchengsite/hexo-theme-oranges"><div class="left"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cover_img/top_img/about/github_logo.webp"/></div><div class="right"><p class="text">hexo-theme-oranges</p><p class="url">https://github.com/zchengsite/hexo-theme-oranges</p></div></a></div>]]></content>
    
    
    <summary type="html">已经有两年没折腾部落格了，不禁感慨，时间过得是真快。这几天没事做，捣鼓捣鼓，发现好多插件版本都太低了</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>探索未来：人工智能如何塑造我们的世界</title>
    <link href="https://blog.imzjw.cn/posts/dfb56fb5/"/>
    <id>https://blog.imzjw.cn/posts/dfb56fb5/</id>
    <published>2024-04-13T14:47:13.000Z</published>
    <updated>2024-04-13T14:47:13.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="人工智能的发展趋势"><a href="#人工智能的发展趋势" class="headerlink" title="人工智能的发展趋势"></a>人工智能的发展趋势</h2><h3 id="自然语言处理的进步"><a href="#自然语言处理的进步" class="headerlink" title="自然语言处理的进步"></a>自然语言处理的进步</h3><p>随着算法的不断优化和计算能力的提升，AI 在理解和生成自然语言方面的能力正在迅速增强。这意味着我们未来的交流可能不再局限于人类之间，而是可以更加自然地与 AI 进行对话。</p><h3 id="机器学习的深度融合"><a href="#机器学习的深度融合" class="headerlink" title="机器学习的深度融合"></a>机器学习的深度融合</h3><p>机器学习作为 AI 的一个重要分支，其在数据分析、预测模型等方面的应用将更加深入。企业和组织可以利用这些技术来提高效率、降低成本，并做出更加精准的决策。</p><h3 id="人工智能伦理的重视"><a href="#人工智能伦理的重视" class="headerlink" title="人工智能伦理的重视"></a>人工智能伦理的重视</h3><p>随着 AI 技术的普及，人们越来越关注其可能带来的伦理问题。如何在保护个人隐私、确保数据安全和避免偏见等方面取得平衡，将成为AI发展中的一个重要议题。</p><h2 id="人工智能如何塑造我们的未来"><a href="#人工智能如何塑造我们的未来" class="headerlink" title="人工智能如何塑造我们的未来"></a>人工智能如何塑造我们的未来</h2><h3 id="工作方式的变革"><a href="#工作方式的变革" class="headerlink" title="工作方式的变革"></a>工作方式的变革</h3><p>AI 的普及将改变我们的工作方式。一方面，自动化和智能化将替代一些重复性和低技能的工作，提高生产效率；另一方面，它也将创造新的职业机会，要求我们不断学习新技能以适应变化。</p><h3 id="教育领域的革新"><a href="#教育领域的革新" class="headerlink" title="教育领域的革新"></a>教育领域的革新</h3><p>AI 技术可以为教育领域带来个性化的学习体验。通过分析学生的学习习惯和能力，AI 能够提供定制化的教学内容和方法，帮助学生更有效地学习。</p><h3 id="社会治理的智能化"><a href="#社会治理的智能化" class="headerlink" title="社会治理的智能化"></a>社会治理的智能化</h3><p>AI 在社会治理方面的应用将使城市管理更加智能化。例如，通过分析交通数据来优化交通流量，或者利用 AI 进行公共安全监控，提高社会治理的效率和水平。</p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>人工智能的发展无疑将为我们带来许多机遇和挑战。我们需要积极拥抱这些变化，同时也要关注可能出现的问题，并采取相应的措施来确保 AI 技术的健康发展。让我们一起期待 AI 如何在未来塑造一个更加智能、高效和美好的世界。</p><p>本文使用 <a href="https://kimi.moonshot.cn/">Kimi.ai - 帮你看更大的世界</a> 演示生成</p>]]></content>
    
    
    <summary type="html">随着算法的不断优化和计算能力的提升，AI 在理解和生成自然语言方面的能力正在迅速增强。这意味着我们未来的交流可能不再局限于人类之间，而是可以更加自然地与 AI 进行对话。</summary>
    
    
    
    <category term="闲聊杂话" scheme="https://blog.imzjw.cn/categories/%E9%97%B2%E8%81%8A%E6%9D%82%E8%AF%9D/"/>
    
    
    <category term="人工智能" scheme="https://blog.imzjw.cn/tags/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/"/>
    
  </entry>
  
  <entry>
    <title>使用 Alist WebDav 搭建图床服务</title>
    <link href="https://blog.imzjw.cn/posts/alist-pic/"/>
    <id>https://blog.imzjw.cn/posts/alist-pic/</id>
    <published>2023-12-04T02:41:15.000Z</published>
    <updated>2024-04-13T11:10:56.000Z</updated>
    
    <content type="html"><![CDATA[<div class="note danger flat"><p>本博主已弃用此方法，但是你想使用也不是不可以，目前博主使用的是 <a href="https://piclist.cn/">PicList</a> + <a href="https://alist.nn.ci/zh/">Alist</a> + <a href="https://typora.io/">Typora</a> 方式！</p></div><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>个人博客，最烦的就是图片的存储了，最开始用的第三方的个人搭建的图床，跑路了，接着用 jsDelivr，后面又用 GitHub、Cloudflare、NPM 使用 <code>npm.elemecdn.com</code> 镜像，折腾来折腾去，没一个稳定的，今年就发现了一个 <a href="https://github.com/alist-org/alist">Alist</a> 这个项目，一直想写这篇文章，一直没时间写（原先是用的 <a href="https://github.com/spencerwooo/onedrive-vercel-index">spencerwooo/onedrive-vercel-index</a> 但是 Vercel 被 Q 了，没办法）</p><p>Alist 官网介绍说一个支持多存储的文件列表 <code>WebDAV</code> 程序，看到这个 <code>WebDav</code>，我就想着是不是就可以搭建一个支持上传 WebDav 的图床服务？就查了下攻略，刚好 Lsky Pro（兰空）图床支持 WebDav 上传，而且后台展示也深得我心！</p><h2 id="预览"><a href="#预览" class="headerlink" title="预览"></a>预览</h2><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://registry.npmmirror.com/yc-pic/1.0.1/files/p/alist-pic/240413-15841a97890e294d.webp" alt="1701659068026.webp"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://registry.npmmirror.com/yc-pic/1.0.1/files/p/alist-pic/240413-8ed6ee429c2c73bf.webp" alt="1701659120988.webp"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://registry.npmmirror.com/yc-pic/1.0.1/files/p/alist-pic/240413-fae7905fcb6ca62d.webp" alt="1701659148239.webp"></p><h2 id="部署步骤"><a href="#部署步骤" class="headerlink" title="部署步骤"></a>部署步骤</h2><ol><li><p>你需要一台服务器 / VPS，可以薅甲骨文的</p></li><li><p>安装 <a href="https://www.bt.cn/new/download.html">Linux 宝塔面板</a>（当然，你也可以手动安装 Lsky Pro，但是宝塔更方便罢了，免除了配置 Nginx）</p></li><li><p>部署 Lsky Pro</p><p>在宝塔界面里，添加站点（安装 MySQL 时选择 &gt;=5.7，PHP &gt;= 8.0.2）</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://registry.npmmirror.com/yc-pic/1.0.1/files/p/alist-pic/240413-70fe22c77c99b8d0.webp" alt="1701660439751.webp"></p><p>进入源码部署页面，在线远程下载，填入以下源码链接进行安装依赖，用其它的可能会有问题，反正宝塔是这样的</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="comment">//github.com/lsky-org/lsky-pro/archive/refs/heads/master.zip</span></span><br></pre></td></tr></table></figure><p>下载好解压之后输入如下安装依赖，安装完成后目录会生成个 <code>vendor</code> 目录。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd /www/wwwroot/lsky-pro-master  # 对应你自己的目录</span><br><span class="line">sudo composer install</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://registry.npmmirror.com/yc-pic/1.0.1/files/p/alist-pic/240413-c96b5d5bab3452de.webp" alt="1701660541934.webp"></p><p>设置运行目录为 <code>/public</code>，并删除如下 <strong>PHP 函数</strong> <code>exec</code>、<code>shell_exec</code>、<code>readlink</code>、<code>symlink</code>、<code>putenv</code>、<code>getenv</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://registry.npmmirror.com/yc-pic/1.0.1/files/p/alist-pic/240413-15ab4bf38475899e.webp" alt="1701661177598.webp"></p><p><strong>安装 PHP 扩展</strong></p><p>进入 PHP 设置 → 安装扩展，选择安装 <code>fileinfo</code>，<code>imagemagick</code> 和 <code>exif</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://registry.npmmirror.com/yc-pic/1.0.1/files/p/alist-pic/240413-2899b135e09590b7.webp" alt="1701661054697.webp"></p><p><strong>添加伪静态配置</strong></p><p>站点设置进入伪静态，输入如下规则</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">location</span> / &#123;</span><br><span class="line">    <span class="attribute">if</span> (!-e <span class="variable">$request_filename</span>) &#123;</span><br><span class="line">        <span class="attribute">rewrite</span><span class="regexp"> ^(.*)$</span> /index.php?s=<span class="variable">$1</span> <span class="literal">last</span>; break;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>设置目录 755 权限</strong></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://registry.npmmirror.com/yc-pic/1.0.1/files/p/alist-pic/240413-2961645376a580c7.webp" alt="1701668383411.webp"></p><p>后面打开域名直接安装即可</p></li><li><p>部署 Alist</p><p>这个简单，跟着<a href="https://alist.nn.ci/zh/">官网</a>一键脚本或者使用 Docker 都可以，然后<a href="https://alist.nn.ci/zh/guide/drivers/common.html">添加存储</a></p></li></ol><h2 id="配置-WebDav"><a href="#配置-WebDav" class="headerlink" title="配置 WebDav"></a>配置 WebDav</h2><p>进入 Lsky Pro 后台，选择储存策略，默认储存策略为本地储存，我们这里使用 AList 提供的 WebDAV 服务创建一个新的储存策略</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://registry.npmmirror.com/yc-pic/1.0.1/files/p/alist-pic/240413-3d55a4808ff643af.webp" alt="1701669626514.webp"></p><table><thead><tr><th align="center">访问域名</th><th align="center">就是上传图片之后，该图片所显示的链接</th></tr></thead><tbody><tr><td align="center">连接地址</td><td align="center">Alist 地址</td></tr><tr><td align="center">认证方式</td><td align="center">选择 Basic</td></tr><tr><td align="center">路径前缀</td><td align="center">/dav/挂载路径，这个路径前缀放到下面再详讲</td></tr><tr><td align="center">用户名</td><td align="center">Alist 用户名，默认 admin</td></tr><tr><td align="center">密码</td><td align="center">Alist 密码</td></tr></tbody></table><p>最后创建储存策略即可上传图片到你 Alist 所挂载的网盘里了</p><p><strong>路径前缀</strong></p><p>这个前缀就是你 Alist 挂载网盘的一个路径，比如我挂载了天翼云盘，名字叫 <code>pic1</code> 那么这个路径前缀就是 <code>/dav/pic1</code>，OneDrive 就叫 <code>/dav/OneDrive</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://registry.npmmirror.com/yc-pic/1.0.1/files/p/alist-pic/240413-fdb5ff26b08f8074.webp" alt="1701670217713.webp"></p><p><strong>上传成功之后，访问链接要输入用户名和密码或者 404？</strong></p><p>这个你需要到 Lsky Pro 站点中配置如下内容</p><p><code>Alist Host:Port/d/挂载路径</code></p><div class="tip warning faa-horizontal animated"><p>/img 要和上一步访问域名的路径保持一致！</p></div><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">location</span> /img &#123;</span><br><span class="line">    <span class="attribute">proxy_pass</span> http://127.0.0.1:5244/d/pic2;</span><br><span class="line">    <span class="attribute">proxy_read_timeout</span> <span class="number">600s</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://registry.npmmirror.com/yc-pic/1.0.1/files/p/alist-pic/240413-f9a6236aa6300687.webp" alt="1701671248164.webp"></p><h2 id="其它方案"><a href="#其它方案" class="headerlink" title="其它方案"></a>其它方案</h2><p>如果不想在网站部署，觉得太麻烦了，想在客户端上传，也不是没有</p><p><strong>Windows</strong></p><ul><li><p><a href="https://piclist.cn/">PicList</a></p><p>在 PicGo 的基础上经过深度的二次开发，不仅完整保留了 PicGo 的所有功能，还增添了许多新的 feature。可以配合 Typora 上传</p></li></ul><p><strong>Android \ IOS</strong></p><ul><li><p><a href="https://pichoro.horosama.com/#/PicHoroDocs/PicHoro">PicHoro</a></p><p>一个用于快速上传图片和管理云存储/图床/SFTP的移动端工具</p></li></ul><h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><ul><li><a href="https://alist.nn.ci/zh/">Alist 文档</a></li><li><a href="https://alist.nn.ci/zh/faq/">Alist 常见问题</a></li><li><a href="https://docs.lsky.pro/docs/free/v2/">Lsky Pro 文档</a></li><li><a href="https://docs.lsky.pro/docs/free/v2/quick-start/questions.html">Lsky Pro 常见问题</a></li></ul>]]></content>
    
    
    <summary type="html">个人博客，最烦的就是图片的存储了，最开始用的第三方的个人搭建的图床，跑路了，接着用 jsDelivr，后面又用 GitHub、Cloudflare、NPM 使用 npm.elemecdn.com 镜像，折腾来折腾去，没一个稳定的</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="图床" scheme="https://blog.imzjw.cn/tags/%E5%9B%BE%E5%BA%8A/"/>
    
  </entry>
  
  <entry>
    <title>onedrive-vercel-index 全新部署方式</title>
    <link href="https://blog.imzjw.cn/posts/fd017eb5/"/>
    <id>https://blog.imzjw.cn/posts/fd017eb5/</id>
    <published>2022-01-18T05:51:28.000Z</published>
    <updated>2022-01-18T05:51:28.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="序"><a href="#序" class="headerlink" title="序"></a>序</h2><p>在此之前，也写过 <code>onedrive-vercel-index</code> 的教程【<a href="https://blog.imzjw.cn/posts/9ce0b4e8/">使用 onedrive-cf-index 的小弟挂载 OneDrive 目录</a>】已经是以前的部署方式了。</p><p>然后今天上 GitHub 瞄了一眼，发现更新了，还是全新改版了，部署方式也变了，索性就折腾了一下。</p><p>更新公告：<a href="https://github.com/spencerwooo/onedrive-vercel-index/discussions/215">New version update: No extra deployment setup is required anymore!</a></p><p><a href="https://docs.spencerwoo.com/getting-started">官方教程</a></p><p>那既然有官方教程，我为什么还要另写一篇呢，因为有小伙伴看了还是部署失败，看不懂，而且还英文文档 😅</p><p>虽然有网页翻译，对吧…</p><div class="note warning flat"><p>博主是 E5 订阅！如果你也是，可以参考一下。</p></div><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><ol><li>Fork 项目：<a href="https://github.com/spencerwooo/onedrive-vercel-index">onedrive-vercel-index</a></li><li>在 Fork 之后的仓库中，打开 <code>config/site.json</code> 文件，修改 <code>userPrincipalName</code> 为你的微软邮箱，还有 <code>baseDirectory</code> 修改为要公开的文件夹，我的是 <code>/Public</code>，如果你没有任何隐私，那就可以直接 <code>/</code>，还有其它的，什么标题，图标，页脚啊，自己看着改就行了，主要就是 <code>userPrincipalName</code> 和 <code>baseDirectory</code></li><li>关于 <code>config/api.json</code>  参考 <a href="https://docs.spencerwoo.com/getting-started#9eb654f8c6af42ebb5b32a21e5747194">Modify API settings (optional)</a>，我是 E5 订阅且还具有管理员权限，不需要修改。</li></ol><p>登录 <a href="https://vercel.com/">Vercel</a>，并在 Vercel 中导入刚刚 Fork 的项目</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fd017eb5/20220118141735.webp" alt="image"></p><p>最后部署等待满屏的烟花即可！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fd017eb5/20220118141757.webp" alt="image"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fd017eb5/20220118141957.webp" alt="image"></p><p>你以为这样就完了吗？No!!!</p><p>在新版的部署方式中，集成了 Redis，作用也就是将那些 Key、Token 存在 Redis 中，下面我们就创建 Redis 连接。所以就用到了 <code>Upstash</code>，一款完全免费、与 Vercel 更好集成的无服务器数据库，具有 Redis API 和持久存储等….</p><p>首先。打开 <a href="https://vercel.com/integrations/upstash">Upstash Integration</a> 点击 Add Integration</p><p>选择一个集成的范围</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fd017eb5/20220118142621.webp" alt="image"></p><p>选择具体的项目，选择 onedrive-vercel-index 这个项目，最后点击 ADD INTEGRATION</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fd017eb5/20220118142641.webp" alt="image"></p><p>接着就会让你注册 <code>Upstash</code> 账号，然后创建一个 Redis 数据库，我这里已经注册过了，就不上图了，地区我是选的 Japan，其它全是默认的</p><p>然后选择 onedrive-vercel-index 项目</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fd017eb5/20220118143249.webp" alt="image"></p><p>最后就已经完美的集成进来了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fd017eb5/20220118143409.webp" alt="image"></p><p>在 Vercel 中打开 onedrive-vercel-index 项目，依次点击 <code>settings - Environment Variables</code>  发现环境变量也自动帮我们添加好了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fd017eb5/20220118143648.webp" alt="image"></p><p>最后记得在 Deployments 页面中 Redeploy 一下</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fd017eb5/20220118143818.webp" alt="images"></p><p>最后一步了</p><p>打开域名，会有三个步骤，根据提示，进行操作就可以了!</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fd017eb5/20220118144649.webp" alt="image"></p><p>成功部署</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fd017eb5/20220118144743.webp" alt="image"></p>]]></content>
    
    
    <summary type="html">在此之前，也写过 onedrive-vercel-index 的教程，已经是以前的部署方式了。然后今天上 GitHub 瞄了一眼，发现更新了，还是全新改版了，部署方式也变了，索性就折腾了一下。</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="Microsoft" scheme="https://blog.imzjw.cn/tags/Microsoft/"/>
    
  </entry>
  
  <entry>
    <title>B23Downloader - B 站视频下载神器</title>
    <link href="https://blog.imzjw.cn/posts/b23downloader/"/>
    <id>https://blog.imzjw.cn/posts/b23downloader/</id>
    <published>2022-01-17T13:45:04.000Z</published>
    <updated>2022-01-17T13:45:04.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="序"><a href="#序" class="headerlink" title="序"></a>序</h2><p>B23Downloader 是一款下载 B 站视频（投稿视频、直播、番剧、电影等）的软件，使用 Qt、C++ 开发，只要输入链接或 BV 号即可解析下载。</p><p>该项目已在 GitHub 开源！</p><div class="tag link"><a class="link-card" title="vooidzero/B23Downloader" href="https://github.com/vooidzero/B23Downloader"><div class="left"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cover_img/top_img/about/github_logo.webp"/></div><div class="right"><p class="text">vooidzero/B23Downloader</p><p class="url">https://github.com/vooidzero/B23Downloader</p></div></a></div><h2 id="下载地址"><a href="#下载地址" class="headerlink" title="下载地址"></a>下载地址</h2><div class="btns rounded grid5">            <a class="button" href='https://github.com/vooidzero/B23Downloader/releases' title='下载地址'><i class='fas fa-download'></i>下载地址</a>          </div><h2 id="食用方法"><a href="#食用方法" class="headerlink" title="食用方法"></a>食用方法</h2><p>下载完成后直接打开即可，就是一个单文件</p><p>然后输入 BV 号即可下载</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b23downloader/20220117215726.webp" alt="images"></p><p>番号也可以</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b23downloader/20220117215948.webp" alt="images"></p><p>直播也是可以的</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b23downloader/20220117220401.webp" alt="images"></p><p>详情请参考【<a href="https://github.com/vooidzero/B23Downloader#%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E">官方文档</a>】</p>]]></content>
    
    
    <summary type="html">B23Downloader 是一款下载 B 站视频（投稿视频、直播、番剧、电影等）的软件，使用 Qt、C++ 开发，只要输入链接或 BV 号即可解析下载。</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="哔哩哔哩" scheme="https://blog.imzjw.cn/tags/%E5%93%94%E5%93%A9%E5%93%94%E5%93%A9/"/>
    
  </entry>
  
  <entry>
    <title>电脑壁纸分享：打工人/学习壁纸</title>
    <link href="https://blog.imzjw.cn/posts/48e55b92/"/>
    <id>https://blog.imzjw.cn/posts/48e55b92/</id>
    <published>2022-01-17T04:43:06.000Z</published>
    <updated>2022-01-17T04:43:06.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="序"><a href="#序" class="headerlink" title="序"></a>序</h2><p>用壁纸将电脑桌面分成多个区域，方便整理桌面文档。加油打工人~</p><div class="note info flat"><p>本文所展示的图都是经过压缩后的图，请下载原图！</p></div><p><strong>壁纸原图下载</strong></p><div class="btns rounded grid5">            <a class="button" href='https://garvey.lanzout.com/i5yEoyw3bej' title='原图下载'><i class='fas fa-download'></i>原图下载</a>          </div><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/48e55b92/2022010101524481.webp" alt="images"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/48e55b92/2022010101523980.webp" alt="image"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/48e55b92/2022010101514318-1024x576.webp" alt="image"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/48e55b92/2022010101514630-1024x576.webp"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/48e55b92/2022010101514996-1024x576.webp" alt="image"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/48e55b92/2022010101515655-1024x576.webp" alt="images"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/48e55b92/2022010101520420-1024x576.webp" alt="image"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/48e55b92/2022010101520934-1024x576.webp" alt="image"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/48e55b92/2022010101521699-1024x576.webp" alt="image"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/48e55b92/2022010101522435-1024x576.webp" alt="images"></p><p>原文：<a href="https://www.maxiaobang.com/12270.html">电脑分区壁纸：打工人/学习系列，高清电脑分区壁纸下载</a></p>]]></content>
    
    
    <summary type="html">用壁纸将电脑桌面分成多个区域，方便整理桌面文档。加油打工人~ 本文所展示的图都是经过压缩后的图，请下载原图！</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="壁纸" scheme="https://blog.imzjw.cn/tags/%E5%A3%81%E7%BA%B8/"/>
    
  </entry>
  
  <entry>
    <title>聊聊现存的 E5 开发者订阅自动续期</title>
    <link href="https://blog.imzjw.cn/posts/e5renewal/"/>
    <id>https://blog.imzjw.cn/posts/e5renewal/</id>
    <published>2021-12-16T04:18:57.000Z</published>
    <updated>2021-12-16T04:18:57.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="序"><a href="#序" class="headerlink" title="序"></a>序</h2><p>Office365 E5 申请好之后，该怎么一直稳定的用下去这是个问题，前面我也讲过搭建 OneIndex 来实现这个续期，但是我也只是听说 OneIndex 的效果不怎么好了，所以本文呢，就来讲讲关于 E5 续期现存的一些实现方法。</p><p>以下实现方法，你可以自行选择用哪个或者全都用，反正原理都是一样的（都是调 API）</p><p>这些实现方法都是增加一定的续期概率，就是玄学，懂吧，并不能保证百分之百就能稳定续期，没人敢保证！</p><p>下面就开始进入正文。</p><h2 id="Microsoft-365-E5-Renew-Plus"><a href="#Microsoft-365-E5-Renew-Plus" class="headerlink" title="Microsoft 365 E5 Renew Plus"></a>Microsoft 365 E5 Renew Plus</h2><p>无需服务器，只要有一台 Windows 操作系统的电脑即可，其前身就是 Microsoft 365 E5 Renew，这个只是一个升级版，其功能性，易用性，美观程度上都要强于旧版。</p><p>原文：<a href="https://blog.csdn.net/qq_33212020/article/details/114482595">E5 调用API续订程序：Microsoft 365 E5 Renew Plus</a></p><h3 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h3><p>请勿开启账号的双重验证功能，如何关闭？参考：<a href="https://blog.csdn.net/qq_33212020/article/details/114482595#t23">关闭 E5 账户登录双重验证</a> 、<a href="https://blog.csdn.net/qq_33212020/article/details/114482595#t24">关闭 Azure 中 API 调用的双重验证</a></p><h3 id="下载安装"><a href="#下载安装" class="headerlink" title="下载安装"></a>下载安装</h3><p>本文只讲 Windows10 操作系统。</p><p>Windows 7、Windows 11、Windows Server 参考 <a href="https://blog.csdn.net/qq_33212020/article/details/114482595#t6">受支持的操作系统及运行环境安装</a></p><div class="btns rounded grid5">            <a class="button" href='https://sundayrx.lanzoux.com/2R2AByh83333' title='下载地址'><i class='fas fa-download'></i>下载地址</a>          </div><p>解压密码（如果有）：<code>SundayRX</code></p><h3 id="注册-Azure-应用程序"><a href="#注册-Azure-应用程序" class="headerlink" title="注册 Azure 应用程序"></a>注册 Azure 应用程序</h3><p><a href="https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade">点击进入 Azure 应用注册</a>  使用 E5 订阅的管理员账号登录。</p><p>登录成功之后，点击新注册</p><ul><li><p>名称</p><p>随便乱填</p></li><li><p>受支持的帐户类型</p><p>选第三个（任何组织目录(任何 Azure AD 目录 - 多租户)中的帐户和个人 Microsoft 帐户(例如，Skype、Xbox) ）</p></li><li><p>重定向 URI</p><p>可以先暂时不填</p></li></ul><p>点击注册</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e5renewal/20211216125638.webp" alt="images"></p><h3 id="配置重定向-URI"><a href="#配置重定向-URI" class="headerlink" title="配置重定向 URI"></a>配置重定向 URI</h3><ol><li><p>先点击<code>概述</code>，然后点击<code>添加重定向 URI</code>，进入重定向 URI 配置界面（因为我配置过了，所以我这里没有显示添加重定向 URI）</p><p>图中打码那块是客户端 ID，一会要用到，可以先有个印象，知道在哪找这个客户端 ID。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e5renewal/20211216125928.webp" alt="image"></p></li><li><p>点击添加平台，再点击移动和桌面应用程序</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e5renewal/20211216130334.webp" alt="image"></p></li><li><p>勾选第一个 URL （<code>https://login.microsoftonline.com/common/oauth2/nativeclient</code>）最后点击配置即可</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e5renewal/20211216130548.webp" alt="images"></p></li><li><p>配置允许公共客户端流，启用无键盘(设备代码流)  改为<code>是</code>即可</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e5renewal/20211216130805.webp" alt="image"></p></li></ol><h3 id="配置-API-权限"><a href="#配置-API-权限" class="headerlink" title="配置 API 权限"></a>配置 API 权限</h3><p>有两种方式</p><ol><li><p><strong>委托的权限</strong></p><p>这种就是用户登录的方式，调用的 API 较多，操作步骤较少简单粗暴，调用成功几率高。</p></li><li><p><strong>应用程序权限</strong></p><p>这种就无需用户登录，但是要添加客户端密码，部分 API 权限受限无法调用（官方限制）还必须手动配置API权限</p></li></ol><p>所以总结来讲，第一种更适合我们，本文也讲第一种方式</p><p>首先，打开刚刚下载内容里面的  <code>Microsoft365 E5 Renew Plus.exe</code> 程序，第一次运行会先回答几个问题，照着回答就行了。</p><p>进入界面之后，<strong>预置设置</strong>、<strong>API 选用库设置</strong>、<strong>运行高级设置</strong> 均默认即可</p><p>点击添加账号</p><p>API 调用方式选择<code>登陆调用</code>，输入你的 E5 账号密码及刚刚注册的客户端 ID，最后点击高级功能中的<strong>自动配置应用程序 API 权限</strong></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e5renewal/20211216131934.webp" alt="images"></p><p>在弹出的登陆页面中输入你的<strong>管理员</strong>账户名和密码登录，不然授权不了，必须是<strong>管理员</strong>的。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e5renewal/20200628135742984.webp" alt="images"></p><p>点击<strong>确定登录</strong>，<strong>开始运行</strong></p><p>查看日志是否调用成功。最后直接最小化挂到后台就不管它了。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e5renewal/20211216133037.webp" alt="images"></p><p>官方提到可以创建一个新的 E5 子账户进行调用 API</p><p>因为 Microsoft 365 E5 Renew Plus中 的部分 API 包含了写操作，例如 OneDrive 的 API，这些 API 在随机模式下会生成大量垃圾邮件和文件（虽然单独为此设立了一个文件夹）部分人可能会对此行为非常介意，而且程序频繁的读写可能会对您正常使用账户造成影响，因此不建议使用管理员账户登录。</p><p>具体可参考：<a href="https://blog.csdn.net/qq_33212020/article/details/114482595#t19">使用程序进行 API 调用</a></p><p>可能你会想到这种具有依赖性，离不开电脑，体验性很差，但是作者也想到了，所以有了网页版的方式</p><h3 id="网页版"><a href="#网页版" class="headerlink" title="网页版"></a>网页版</h3><p>具体可参考：<a href="https://blog.csdn.net/qq_33212020/article/details/119747634">E5 调用 API 续订服务：Microsoft 365 E5 Renew X</a></p><p>本文不在阐述。</p><h2 id="E5Sub-Bot"><a href="#E5Sub-Bot" class="headerlink" title="E5Sub Bot"></a>E5Sub Bot</h2><p>E5SubBot 是 Office365 E5 自动续订机器人，通过 Telegram Bot 自动调用 Outlook API 尝试自动续订 E5 订阅（每三小时调用一次）</p><p>程序基于 Golang + MySQL 开发。</p><p>GitHub 地址</p><p><a href="https://github.com/iyear/E5SubBot">ghcard iyear/E5SubBot</a></p><div class="btns rounded grid5">            <a class="button" href='https://t.me/E5Sub_bot' title='作者搭建的 Bot'><i class='fas fa-robot'></i>作者搭建的 Bot</a><a class="button" href='https://t.me/e5subbot' title='交流群组'><i class='fas fa-sms'></i>交流群组</a>          </div><p><strong>特性：</strong></p><ul><li>自动续订 E5 订阅（可自定义调用频率）</li><li>易于管理的简单账户系统</li><li>完善的任务执行反馈</li><li>便捷授权</li><li>使用并发加速</li></ul><p><strong>原理：</strong>由于 E5 订阅是开发者订阅，只要调用相关 API，保持 API 的活跃就有可能续期，本程序就是通过调用 Outlook ReadMail API 实现玄学的续订方式，不保证续订效果。</p><p>为了不必要的重复造轮子，而且自己折腾还是有点门槛的，建议直接使用作者的 Bot 来续订！</p><h3 id="注册-Azure-应用程序-1"><a href="#注册-Azure-应用程序-1" class="headerlink" title="注册 Azure 应用程序"></a>注册 Azure 应用程序</h3><p><a href="https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade">点击进入 Azure 应用注册</a>  使用 E5 订阅的管理员账号登录。</p><p>登录成功之后，点击新注册</p><ul><li><p>名称</p><p>随便乱填</p></li><li><p>受支持的帐户类型</p><p>选第三个（任何组织目录(任何 Azure AD 目录 - 多租户)中的帐户和个人 Microsoft 帐户(例如，Skype、Xbox) ）</p></li><li><p>重定向 URI</p><p>输入 <code>http://localhost/e5sub</code></p></li></ul><p>最后点击注册，记录客户端 ID</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e5renewal/20211216134954.webp" alt="image"></p><p>点击右侧边栏的<strong>证书与密码</strong>，创建一个客户端密码，期限选择 24 个月，并记录起来，因为只会显示一次。</p><p>点击右侧边栏的 <strong>API 权限</strong>，添加权限，选择 <code>Microsoft Graph - 委托的权限</code></p><p>在下面勾选上 <code>openid</code>、<code>offline_access</code>、<code>mail.read</code> 并添加</p><p>添加完之后点击<strong>授权管理员同意</strong>，最后点击<code>是</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e5renewal/20211216140336.webp" alt="images"></p><h3 id="E5Sub-配置"><a href="#E5Sub-配置" class="headerlink" title="E5Sub 配置"></a>E5Sub 配置</h3><p>这里就直接使用作者搭建的 Bot 了，当然，你想重复造轮子也可以，参考 <a href="https://github.com/iyear/E5SubBot#deploy-your-own-bot">官方 GitHub</a> 或者我也可以水一篇搭建教程 😃</p><ol><li><p>打开作者的 <a href="https://t.me/E5Sub_bot">@E5Sub_bot</a></p></li><li><p>发送 <code>/bind</code> 指令，回复 客户端 ID 和客户端密码。格式为 <strong>客户端 ID + 空格 + 客户端密码</strong></p><p>例如：<code>7612-2uas127-2n31 ~g_ajse3n913-99o2ik</code></p></li><li><p>点击直达，授权登录之后把浏览器地址栏那一串地址全选复制后面再加个空格输入别名，只是便于知道是哪个账号而已</p><p>例如：<code>http://localhost/e5sub?code=0.Axxxxxxxxxxxxxxxxxxx 账号1</code></p></li></ol><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e5renewal/20211216141028.webp" alt="images"></p><p>成功提示图</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e5renewal/20211216141822.webp" alt="images"></p><h2 id="GitHub-AutoApi"><a href="#GitHub-AutoApi" class="headerlink" title="GitHub AutoApi"></a>GitHub AutoApi</h2><p>大佬都删库跑路了，不过你在 GitHub 搜一下应该还有一些 fork 的版本。</p><p>不过我现在已不用 AutoApi 这种方式了！</p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>还有哪些方式，可以留言评论噢！</p>]]></content>
    
    
    <summary type="html">Office365 E5 申请好之后，该怎么一直稳定的用下去这是个问题，前面我也讲过搭建 OneIndex 来实现这个续期，但是我也只是听说 OneIndex 的效果不怎么好了</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="Microsoft" scheme="https://blog.imzjw.cn/tags/Microsoft/"/>
    
  </entry>
  
  <entry>
    <title>Why do people still use Java, if Java is behind technologically</title>
    <link href="https://blog.imzjw.cn/posts/8cf97d8f/"/>
    <id>https://blog.imzjw.cn/posts/8cf97d8f/</id>
    <published>2021-12-12T12:56:00.000Z</published>
    <updated>2021-12-12T12:56:00.000Z</updated>
    
    <content type="html"><![CDATA[<p>First off, there are a lot of jobs for Java developers, so that is one reason, but why do people still use Java, including for new projects?</p><p>More recently popular high-level languages like python or ruby can be better for developer productivity, flexibility, and fast iteration due to less code cruft and verbosity. But the dynamic nature of these languages is fantastic for many broad applications, starts to break down when a project becomes very large, lots of developers are involved, or when speed and fault-tolerance are critical.</p><p>There are techniques and conventions to work around the code stability problems of dynamic typing, but techniques and conventions mean people need to follow them, and even then, there are vulnerabilities that are difficult to prevent. Take for example PHP, which is used throughout Facebook for back-end coding, was extended by Facebook to give it static typing and dynamic compilation so that it could deliver the speed and stability you would get when using technologies like Java. Exotic languages, like Scala, Haskel, Erlang, and Golang, will mainly be for specific applications best suited to them.</p><p>Java on the other hand is still best-in-class for many applications. It is the best way to build a rock-solid, fast, scalable, bug-free back-end system. It’s got the fastest JVM. Only C or C++ is faster, and only in certain narrow circumstances like compute algorithm optimization. Java is also the language of Android, the most broadly deployed smartphone OS on the planet.</p><p>Some have pointed out in the comments that Rust is an up-and-coming language, and Go is getting a strong foothold as a scalable back-end server language. Java is probably not the “best” these days in terms of abstraction and execution speed, but it still has a tremendously large installed base of libraries that these newer languages don’t have yet and might not for a long time to come.</p><a class="btn-beautify purple" href="https://dev.to/ifycoool/why-do-people-still-use-java-if-java-is-behind-technologically-1nh7"   title="原文"><i class="far fa-hand-point-right"></i><span>原文</span></a>]]></content>
    
    
    <summary type="html">First off, there are a lot of jobs for Java developers, so that is one reason, but why do people still use Java, including for new projects?</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Java" scheme="https://blog.imzjw.cn/tags/Java/"/>
    
  </entry>
  
  <entry>
    <title>使用 UnblockNeteaseMusic 解锁网易云音乐灰色无版权歌曲</title>
    <link href="https://blog.imzjw.cn/posts/c813625b/"/>
    <id>https://blog.imzjw.cn/posts/c813625b/</id>
    <published>2021-09-22T08:01:21.000Z</published>
    <updated>2021-09-22T08:01:21.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><p>UnblockNeteaseMusic，它是一款可以在网易云音乐里面能听到无版权的歌曲，说白了就是解锁网易云音乐客户端变灰的歌曲。（给这个灰色的歌曲换了个音乐源）</p><p>使用了 QQ / 虾米 / 百度 / 酷狗 / 酷我 / 咪咕 / JOOX 音源替换变灰歌曲链接（默认仅启用一、五、六）</p><h2 id="前提准备"><a href="#前提准备" class="headerlink" title="前提准备"></a>前提准备</h2><ol><li>一台服务器 / VPS</li><li>网易云音乐<a href="https://music.163.com/#/download">客户端</a></li></ol><h2 id="开始安装"><a href="#开始安装" class="headerlink" title="开始安装"></a>开始安装</h2><p>UnblockNeteaseMusic 的安装方式有很多，而本文呢，就讲我个人最喜欢的一种方式，使用的是 Docker 安装的方式。</p><h3 id="安装-Docker"><a href="#安装-Docker" class="headerlink" title="安装 Docker"></a>安装 Docker</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">CentOS 7、Debian、Ubuntu 安装</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">如果是国内鸡可以使用 https://get.daocloud.io/docker 来替换 https://get.docker.com/</span></span><br><span class="line">curl -sSL https://get.docker.com/ | sh</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">启动 docker</span></span><br><span class="line">sudo systemctl enable docker</span><br><span class="line">sudo systemctl start docker</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">校验安装，如果返回版本号则说明安装成功</span></span><br><span class="line">docker -v</span><br></pre></td></tr></table></figure><h3 id="运行镜像"><a href="#运行镜像" class="headerlink" title="运行镜像"></a>运行镜像</h3><p>我们可以先直接使用 <code>docker run</code>  命令，不用先 <code>docker pull</code> 镜像，因为在 docker run 的时候他会去找这个镜像，发现没有它自己会进行一个 docker pull 的操作！</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run --restart=always --name unblockmusic -d -p 2333:8080 nondanee/unblockneteasemusic</span><br></pre></td></tr></table></figure><p>–name：容器名，看你喜欢叫什么，2333 则是本地端口号（指定一个本地的端口来映射容器内部的端口）自行修改，8080 是容器内部端口，无需更改。</p><p>接着我们输入 <code>docker ps</code> 查看当前正在运行的容器</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">CONTAINER ID   IMAGE                          COMMAND                  CREATED          STATUS          PORTS                                                 NAMES</span><br><span class="line">a4159e2a09ea   nondanee/unblockneteasemusic   <span class="string">&quot;node app.js&quot;</span>            27 seconds ago   Up 26 seconds   8081/tcp, 0.0.0.0:2333-&gt;8080/tcp, :::2333-&gt;8080/tcp   unblockmusic</span><br></pre></td></tr></table></figure><p>最后放行端口！</p><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><p><strong>PC：</strong></p><ol><li>打开网易云音乐客户端，打开设置</li><li>找到工具，选择自定义代理，输入服务器 IP 地址和端口即可，点击测试，弹出【该代理可使用】</li><li>恭喜你，已经解锁网易云无版权歌曲了</li><li>最后点击【确定】重启网易云音乐客户端！</li></ol><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c813625b/20210922162746.webp" alt="Windows"></p><p><strong>Android：</strong></p><ol><li>打开手机设置，或者长按 WIFI 图标即可进入</li><li>选择已连接的 WIFI 对它进行一个高级设置</li><li>代理选择手动，然后输入服务器 IP 和端口号即可</li></ol><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c813625b/20210922164116.webp" alt="Android" height="500" /><p><strong>IOS：</strong></p><ul><li>我没有，所以我不知道</li></ul><h2 id="效果预览"><a href="#效果预览" class="headerlink" title="效果预览"></a>效果预览</h2><p>使用前：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c813625b/20210922164629.webp" alt="before use"></p><p>使用后：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c813625b/20210922164816.webp" alt="after use"></p>]]></content>
    
    
    <summary type="html">UnblockNeteaseMusic，它是一款可以在网易云音乐里面能听到无版权的歌曲，说白了就是解锁网易云音乐客户端变灰的歌曲。（给这个灰色的歌曲换了个音乐源）</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="网易云" scheme="https://blog.imzjw.cn/tags/%E7%BD%91%E6%98%93%E4%BA%91/"/>
    
  </entry>
  
  <entry>
    <title>介绍一款可免费搭建属于自己的 RSS 服务</title>
    <link href="https://blog.imzjw.cn/posts/inkrss/"/>
    <id>https://blog.imzjw.cn/posts/inkrss/</id>
    <published>2021-07-28T13:45:55.000Z</published>
    <updated>2021-07-29T05:30:31.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><p>首先得知道 RSS 是什么？</p><p>RSS（全称：RDF Site Summary；Really Simple Syndication）中文译作，也称<strong>聚合内容</strong>，是一种消息来源格式规范，用以<strong>聚合</strong>经常发布更新资料的网站，例如博客文章、新闻、音频或视频的网摘。摘自——<a href="https://zh.wikipedia.org/wiki/RSS">维基百科 - RSS</a> </p><p>这太官方了，其实通俗点讲就是<strong>窃听</strong>，比如我订阅一个网站，那网站发布了什么新的内容，就会第一时刻通知我。这就很像设计模式里的 <a href="https://zh.wikipedia.org/wiki/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F">观察者模式</a></p><p>然后某位 “道友” 给我转发了一个项目</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/inkrss/20210729001852.webp" alt="images"></p><p>我一眼就喵上了无需服务器，这和我的想法非常符合！</p><p>而且这个项目的初衷就是免费。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/inkrss/20210729001723.webp" alt="images"></p><p>bai piao 谁不爱呀！</p><p>GitHub 地址：<a href="https://github.com/pureink/inkrss">pureink/inkrss</a></p><h2 id="前期准备"><a href="#前期准备" class="headerlink" title="前期准备"></a>前期准备</h2><ol><li><p>安装 <a href="https://nodejs.org/zh-cn/download/releases/">node</a>，推荐 12.x 版本，没必要装最新（长期支持版即可）安装完成后在命令行输入 <code>npm -v</code> 或 <code>node -v</code> ，如返回版本号说明安装成功！</p></li><li><p>安装 <code>wrangler</code>，输入 <code>wrangler -V</code>  如返回版本号说明安装成功！</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i @cloudflare/wrangler -g</span><br></pre></td></tr></table></figure></li><li><p>在 <a href="https://dash.cloudflare.com/sign-up">Cloudflare 官网</a> 进行注册账号并验证邮箱成功后，在右侧找到 <code>Workers</code> 并注册一个子域名，例如：<code>xxx.workers.dev</code></p></li><li><p>在命令行输入以下命令进行登录（回车之后输入 <strong>y</strong>）就会跳转到浏览器进行授权</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wrangler login</span><br></pre></td></tr></table></figure><p>但也会有特殊情况，如果授权后，命令行没有收到返回的 <code>token</code> 的情况下，可以使用以下方式进行登录</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wrangler config</span><br></pre></td></tr></table></figure><p>然后浏览器打开 <a href="https://dash.cloudflare.com/profile/api-tokens">api-tokens</a>  选择创建令牌，令牌模式选择编辑 Cloudflare Workers</p><p>其中账户资源选择【所有账户】区域资源选择【所有区域】其他选项保持默认即可，接着把生成好的 token 复制粘贴到命令行中并回车。</p><div class="note warning flat"><p>如果 <code>wrangler login</code> 能成功收到返回的 token 可忽略这一步！</p></div></li></ol><h2 id="部署"><a href="#部署" class="headerlink" title="部署"></a>部署</h2><p>首先克隆项目</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/pureink/inkrss</span><br></pre></td></tr></table></figure><p>如您当前的网络环境克隆的非常慢，可以使用某宝的加速链接</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com.cnpmjs.org/pureink/inkrss.git</span><br></pre></td></tr></table></figure><p>或者也可以配置戴笠，然后再进行克隆</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git config --global http.proxy socks5://127.0.0.1:7890</span><br><span class="line">git <span class="built_in">clone</span> https://github.com/pureink/inkrss</span><br></pre></td></tr></table></figure><p>克隆完成后进入项目文件夹里输入以下命令并回车</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wrangler kv:namespace create <span class="string">&quot;KV&quot;</span></span><br></pre></td></tr></table></figure><p>就会返回 <code>binding</code> 和 <code>id</code>，复制并粘贴到 <code>./wrangler.toml</code> 文件里的 <code>kv_namespaces</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/inkrss/20210728223129.webp" alt="images"></p><p>返回到 Cloudflare <a href="https://www.cloudflare.com/">官网</a> 点击 <code>Workers</code> ，复制账户 ID 到  <code>./wrangler.toml</code>  里的 <code>account_id</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/inkrss/20210728223340.webp" alt="images"></p><h3 id="通知方式"><a href="#通知方式" class="headerlink" title="通知方式"></a>通知方式</h3><p>目前该项目通知方式有：</p><ul><li>Telegram（包括即时预览和机器人订阅，功能丰富，受限于网络）</li><li>Bark（部署最便捷，受限于平台）</li><li>Wechat（部署较麻烦，仅支持纯文本，适用性广）</li></ul><p>作者说后续会支持 Slack，Discord，钉钉等其他通知方式。</p><p>而本文就讲一个 Telegram 的方式，其它的自己琢磨一下就会了。</p><p>首先在 <code>./config.js</code> 修改 mode 为你想要的通知方式，本文就讲 telegram，故这里填 telegram，随后修改  <code>./config/telegram</code> 文件夹下的  <code>config.json</code></p><p>根据 <a href="https://github.com/pureink/inkrss/blob/main/config/telegram/readme.md">readme.md</a> 进行参数配置。</p><p>这里我粗略讲下：</p><table><thead><tr><th align="center">参数</th><th align="center">含义</th></tr></thead><tbody><tr><td align="center">SECRET_PATH</td><td align="center">就是个路径（注意：不是网址，是路径，例如：abc、sub、123）</td></tr><tr><td align="center">PARSE_URL</td><td align="center">解析 XML 的 API，可以<strong>适量</strong>使用作者的 API 接口：<code>https://inkrssparse.vercel.app</code><br>不过建议还是自建，参考文档 注意事项里的 <a href="https://github.com/pureink/inkrss#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9">第 4 条</a> <br>（Vercel 就好像免费 100 G 流量，个个都用作者接口的话…）</td></tr><tr><td align="center">TG_TOKEN</td><td align="center">Telegram Bot 的 Token，找它 <a href="https://t.me/BotFather">@BotFather</a> 进行创建机器人<br>发送 <code>/newbot</code>  输入机器人的名字，比如：我的专属 RSS 机器人 ，接着再输入该机器人的标识，比如 <code>my_rss_bot</code>（需以 bot 结尾）然后就出现该机器人的 Token 了</td></tr><tr><td align="center">TELEGRAPH_TOKEN</td><td align="center">用于提供即时预览，请访问此 <a href="https://api.telegra.ph/createAccount?short_name=ink&author_name=inkrss">URL</a> 获得</td></tr><tr><td align="center">TG_USERID</td><td align="center">与 <a href="https://t.me/userinfobot">@userinfobot</a> 对话，获取自己的 ID</td></tr><tr><td align="center">TG_SENDID</td><td align="center">发送对象的 ID，可以是频道，群组或个人</td></tr></tbody></table><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/inkrss/20210728224405.webp" alt="images"></p><p>最后输入以下命令进行发布</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wrangler publish</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/inkrss/20210729001022.webp" alt="images"></p><p>访问：<code>https://ink-rss.xxx.workers.dev/&#123;你配置的路径&#125;</code></p><h3 id="Telegram-Bot-配置"><a href="#Telegram-Bot-配置" class="headerlink" title="Telegram Bot 配置"></a>Telegram Bot 配置</h3><p>目前仅支持四个命令（还没有做完）</p><ul><li><p>/sub：订阅，例：<code>/sub https://blog.imzjw.cn/atom.xml</code></p></li><li><p>/list：查看所有订阅</p></li><li><p>/unsub：取消某个订阅，例：<code>/unsub https://rsshub.app/v2ex/topics/latest</code></p></li><li><p>/unsuball：取消所有订阅</p></li></ul><p>使用 Telegram 不仅可以使用网页，还包含借助 Telegraph 提供的即时预览功能（instant view）以及一个提供增删查功能的机器人。部署成功后访问</p><p><code>https://api.telegram.org/bot&lt;your token&gt;/setwebhook?url=https://ink-rss.xxx.workers.dev/&#123;你配置的路径&#125;</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/inkrss/20210729005925.webp" alt="images"></p><p>即可开始使用 Bot 进行订阅，注意替换 token 以及 URL</p><p>为了方便，我们可以在 BotFather 那里给机器人添加指令</p><ol><li><p>发送 /mybots，选择你的 RSS Bot</p></li><li><p>选择 Edit Bot –&gt; Edit Commands</p></li><li><p> 向 BotFather 发送</p></li></ol>   <figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">sub - 订阅</span><br><span class="line">list - 查看所有订阅</span><br><span class="line">...</span><br><span class="line">...</span><br></pre></td></tr></table></figure><p>过一会，你的机器人就有这些指令了</p><p>赶紧发个 <code>/sub https://blog.imzjw.cn/atom.xml</code> 测试一下把！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/inkrss/20210729010623.webp" alt="images"></p><div class="note info flat"><p>2021-07-29 补充</p><p>推荐一个最全的 RSS 订阅源</p><p>万物皆可 RSS：<a href="https://docs.rsshub.app/">RSSHub</a></p></div><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>我今天也遇到挺多问题的，就当小白鼠了。但是部署成功之后，细想一下</p><p>其实这项目还是挺简单的，前置要求都弄好之后无非就是</p><ol><li><code>wrangler kv:namespace create &quot;KV&quot;</code></li><li>修改根目录下的  <code>config.js</code>  与  <code>wrangler.toml</code></li><li>修改  <code>./config/telegram/config.json</code></li><li><code>wrangler publish</code></li></ol><p>最后作者还说这项目刚问世还不是很完善，有任何问题可以随时提 <a href="https://github.com/pureink/inkrss/issues/new">issues</a></p><p>参考：</p><ul><li><a href="https://github.com/pureink/inkrss/blob/main/README.md">pureink/inkrss</a></li></ul><p>特别感谢：</p><ul><li><a href="https://github.com/pureink">pureink</a></li></ul>]]></content>
    
    
    <summary type="html">首先得知道 RSS 是什么？RSS（全称：RDF Site Summary；Really Simple Syndication）中文译作，也称聚合内容，是一种消息来源格式规范，用以聚合经常发布更新资料的网站</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="RSS" scheme="https://blog.imzjw.cn/tags/RSS/"/>
    
  </entry>
  
  <entry>
    <title>使用 GitHub Actions 自动构建 Dockerfile 并推送到 Docker Hub</title>
    <link href="https://blog.imzjw.cn/posts/2c98841c/"/>
    <id>https://blog.imzjw.cn/posts/2c98841c/</id>
    <published>2021-07-23T13:30:32.000Z</published>
    <updated>2021-07-23T13:30:32.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><p>为什么要用 GitHub Actions 来为我们构建 Dockerfile 呢？我直接在服务器上 <code>docker build</code> 不行么？你这不是多此一举吗</p><p>肯定有人会有这种想法，因为他们不知道也没用过国内的服务器…</p><p>在国内服务器上构建的话，你甚至都可以开一把召唤师峡谷。</p><p>所以用国内服务器的可以利用 GitHub Actions 来帮我们构建  <code>Dockerfile</code>  并  <code>push</code>  到  <code>Docker Hub</code></p><h2 id="开始"><a href="#开始" class="headerlink" title="开始"></a>开始</h2><p>这里我以 Spring Boot 项目为 Demo，不过你得先去注册 <a href="https://hub.docker.com/">Docker Hub</a> 账号。</p><p>新建一个 Spring Boot 工程，里面的代码很简单，就是用来测试的</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DockerController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;success&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">actions</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;This is the Docker image I built using GitHub Actions. 🎉&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>application.yaml</code>  里，就配置了一个 8989 端口，然后就没了，最后记得打包（把打包好的移进根目录）</p><p>在项目根目录新建并编写  <code>Dockerfile</code>（也是网上抄来的，哈哈）</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 基础镜像 jdk1.8</span></span><br><span class="line"><span class="keyword">FROM</span> java:<span class="number">8</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 作者</span></span><br><span class="line"><span class="keyword">MAINTAINER</span> sudojia</span><br><span class="line"></span><br><span class="line"><span class="comment"># 把可执行 jar 包复制到基础镜像的根目录下</span></span><br><span class="line"><span class="keyword">ADD</span><span class="language-bash"> actions_build_springboot_docker-1.0-RELEASE.jar /actions_build_springboot_docker.jar</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 镜像要暴露的端口，如要使用端口，在执行 docker run 命令时使用 -p 生效</span></span><br><span class="line"><span class="keyword">EXPOSE</span> <span class="number">8989</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 在镜像运行为容器后执行的命令</span></span><br><span class="line"><span class="keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="string">&quot;java&quot;</span>,<span class="string">&quot;-Djava.security.egd=file:/dev/./urandom&quot;</span>,<span class="string">&quot;-jar&quot;</span>,<span class="string">&quot;/actions_build_springboot_docker.jar&quot;</span>]</span></span><br></pre></td></tr></table></figure><p>项目结构就这样，只要 Dockerfile 和 JAR 包就好了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/2c98841c/20210723214018.webp" alt="images"></p><p>接下来就开始编写 Actions 代码了</p><p>在项目根目录创建  <code>.github/workflows/main.yml</code></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">name:</span> <span class="string">BuildDockerfileImage</span></span><br><span class="line"></span><br><span class="line"><span class="attr">on:</span></span><br><span class="line">  <span class="comment"># 防止 Fork 乱用 actions 设置只能手动触发构建</span></span><br><span class="line">  <span class="attr">workflow_dispatch:</span></span><br><span class="line">  <span class="attr">repository_dispatch:</span></span><br><span class="line">    <span class="attr">types:</span> <span class="string">build_docker_image</span></span><br><span class="line"></span><br><span class="line"><span class="attr">jobs:</span></span><br><span class="line">  <span class="attr">build-and-push:</span></span><br><span class="line">    <span class="attr">runs-on:</span> <span class="string">ubuntu-latest</span></span><br><span class="line">    <span class="attr">steps:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Checkout</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">actions/checkout@master</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Set</span> <span class="string">up</span> <span class="string">QEMU</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">docker/setup-qemu-action@v1</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Set</span> <span class="string">up</span> <span class="string">Docker</span> <span class="string">Buildx</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">docker/setup-buildx-action@v1</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Login</span> <span class="string">to</span> <span class="string">DockerHub</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">docker/login-action@v1</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">username:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.DOCKERHUB_USERNAME</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">password:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.DOCKERHUB_TOKEN</span> <span class="string">&#125;&#125;</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">构建并推送到</span> <span class="string">Dockerhub</span> <span class="string">镜像仓库</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">docker/build-push-action@v2</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">context:</span> <span class="string">.</span></span><br><span class="line">          <span class="attr">file:</span> <span class="string">./Dockerfile</span> <span class="comment"># Dockerfile 位置</span></span><br><span class="line">          <span class="attr">platforms:</span> <span class="string">linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64</span></span><br><span class="line">          <span class="attr">push:</span> <span class="literal">true</span></span><br><span class="line">          <span class="attr">tags:</span> <span class="string">|</span></span><br><span class="line">            <span class="string">xxx/actions_build_springboot</span> <span class="comment"># 改成你自己的， dockerhub用户名/镜像名</span></span><br></pre></td></tr></table></figure><div class="note warning flat"><p>注意：最后一行的 tags 配置项，需修改，用户名/镜像名（镜像名看你喜欢取什么）</p></div><p>接下来就是 GitHub 上的操作了</p><ol><li>新建仓库</li><li>在仓库配置两条密钥（<code>Setting -&gt; Secrets -&gt; New repository secret</code>）</li></ol><table><thead><tr><th align="center">Secrets Name</th><th align="center">Value</th></tr></thead><tbody><tr><td align="center">DOCKERHUB_USERNAME</td><td align="center">Docker Hub 的用户名</td></tr><tr><td align="center">DOCKERHUB_TOKEN</td><td align="center">Docker Hub Token，前往<a href="https://hub.docker.com/settings/security?generateToken=true">生成</a></td></tr></tbody></table><p>随后就可以直接把项目推送到 GitHub 上了。</p><p>点击仓库中的 Actions，点击  <code>Run workflow</code> （因为避免一些麻烦事，所以就设置只能手动触发构建）</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/2c98841c/20210723225257.webp" alt="images"></p><p>然后在 Docker Hub 就看到此镜像了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/2c98841c/20210723230006.webp" alt="images"></p><p>打开 SSH 工具连接服务器把镜像拉取下来，拉取完成之后执行以下命令开始测试。</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">docker run -d -p 8989:8989 [IMAGES]</span><br><span class="line"><span class="comment"># -d 是后台运行容器</span></span><br><span class="line"><span class="comment"># -p 指定端口映射（前者是宿主机端口，后者是容器的端口）一般改前者，也可以不改，可以和容器的端口一致</span></span><br><span class="line"><span class="comment"># [IMAGES] 也就是你的镜像名或者镜像 ID 都可以的啦</span></span><br></pre></td></tr></table></figure><p>打开浏览器访问  <code>http://IP:8989/success</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/2c98841c/20210723230649.webp" alt="images"></p><p>完结！</p><p>参考：</p><ul><li><a href="https://github.com/docker/build-push-action">docker/build-push-action</a></li></ul>]]></content>
    
    
    <summary type="html">为什么要用 GitHub Actions 来为我们构建 Dockerfile 呢？我直接在服务器上 docker build 不行么？你这不是多此一举吗，肯定有人会有这种想法，因为他们不知道也没用过国内的服务器</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="GitHub Actions" scheme="https://blog.imzjw.cn/tags/GitHub-Actions/"/>
    
  </entry>
  
  <entry>
    <title>Git 同时 Push 到 GitHub、Gitee 等多个平台</title>
    <link href="https://blog.imzjw.cn/posts/7956c904/"/>
    <id>https://blog.imzjw.cn/posts/7956c904/</id>
    <published>2021-07-22T12:45:28.000Z</published>
    <updated>2021-07-22T12:45:28.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>其实不仅 Hexo 可以推送到多个平台，Git 也是可以的，貌似 Hexo 的原理就是和 Git 的一样</p><p>首先在 <code>C:\Users\baby\.ssh</code> 下新建 <code>config</code> 文件，啥后缀都不要。</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># GitHub                                                                    </span></span><br><span class="line">Host github.com</span><br><span class="line">HostName github.com</span><br><span class="line">User git</span><br><span class="line">IdentityFile ~/.ssh/id_rsa</span><br><span class="line"></span><br><span class="line"><span class="comment"># Gitee                                                                 </span></span><br><span class="line">Host gitee.com</span><br><span class="line">HostName gitee.com</span><br><span class="line">User git</span><br><span class="line">IdentityFile ~/.ssh/id_rsa_gitee <span class="comment"># 自己 ssh-keygen -t rsa -C 再重新生成一份绑定到码云上</span></span><br></pre></td></tr></table></figure><h2 id="创建仓库"><a href="#创建仓库" class="headerlink" title="创建仓库"></a>创建仓库</h2><p>分别在 <a href="https://github.com/new">GitHub</a> 和 <a href="https://gitee.com/projects/new">Gitee</a> 创建仓库</p><p>我 GitHub 上的仓库</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">git@github.com:xxx/git-demo.git</span></span><br></pre></td></tr></table></figure><p>Gitee 上的仓库</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">git@gitee.com:xxx/git-demo.git</span></span><br></pre></td></tr></table></figure><p>然后在项目里  <code>git init</code></p><p>之后添加 GitHub 的远程仓库</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git remote add github git@github.com:xxx/git-demo.git</span><br></pre></td></tr></table></figure><p>Gitee 的</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git remote add gitee git@gitee.com:xxx/git-demo.git</span><br></pre></td></tr></table></figure><p>可以输入 <code>git remote -v</code> 命令查看仓库信息</p><p>最后直接 <code>push</code> 代码</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git push github master</span><br><span class="line">git push gitee master</span><br></pre></td></tr></table></figure><table><thead><tr><th align="center">GitHub</th><th align="center">Gitee</th></tr></thead><tbody><tr><td align="center"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7956c904/20210722210245.webp" alt="images"></td><td align="center"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7956c904/20210722210412.webp" alt="images"></td></tr></tbody></table><p>为了推送方便，我们可以编写个 <code>bash</code> 脚本。</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#! /bin/bash</span></span><br><span class="line">git add .</span><br><span class="line">git commit -m <span class="string">&quot;Update by xiaojia&quot;</span></span><br><span class="line">git push github master</span><br><span class="line">git push gitee master</span><br><span class="line"><span class="built_in">read</span> info</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7956c904/20210722210926.webp" alt="images"></p><p>完结！</p>]]></content>
    
    
    <summary type="html">其实不仅 Hexo 可以推送到多个平台，Git 也是可以的，貌似 Hexo 的原理就是和 Git 的一样，首先在 C:&#92;Users&#92;baby&#92;.ssh 下新建 config 文件</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="Git" scheme="https://blog.imzjw.cn/tags/Git/"/>
    
  </entry>
  
  <entry>
    <title>免费使用 GitHub Actions 自动打包部署 Spring Boot 项目到服务器</title>
    <link href="https://blog.imzjw.cn/posts/d347d656/"/>
    <id>https://blog.imzjw.cn/posts/d347d656/</id>
    <published>2021-06-29T08:13:35.000Z</published>
    <updated>2021-06-29T08:13:35.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>曾经我们部署 Spring Boot 项目的时候，还要手动 mvn clean install，然后再把 JAR 包上传到服务器，最后 <code>java -jar</code>，后面有了 <a href="https://www.jenkins.io/">jenkins</a> CI 工具让我们一劳永逸，但是本文讲的不是 jenkins，而是 GitHub Actions</p><h2 id="GitHub-Actions"><a href="#GitHub-Actions" class="headerlink" title="GitHub Actions"></a>GitHub Actions</h2><p>GitHub Actions 是 GitHub 推出的持续集成（Con­tin­u­ous in­te­gra­tion  简称 CI）服务，它提供了配置非常不错的虚拟服务器环境，基于它可以进行构建、测试、打包、部署项目。简单来讲就是将软件开发中的一些流程交给云服务器自动化处理，比如我们开发者吧代码  <code>push</code>  到 GitHub 后它就会自动测试、编译、发布，有了这么一个持续集成服务之后开发者就可以专心于写代码，其他什么琐事就不用管了，大大的提高开发效率。</p><p>在原先 2019 年 11 月的时候，GitHub Actions 还处在测试阶段，需要申请才能使用，而现在已经完全可以免费使用了，免费归免费，但是 GitHub 官方也对使用 GitHub Actions 的做出了一些限制。 <a href="https://docs.github.com/cn/actions/reference/usage-limits-billing-and-administration">使用限制</a></p><h2 id="正式开始"><a href="#正式开始" class="headerlink" title="正式开始"></a>正式开始</h2><p>环境</p><ul><li>Spring Boot 2.2.6.RELEASE</li><li>IntelliJ IDEA 2020.3.4</li><li>JDK 1.8</li><li>Apache Maven 3.6.3</li><li>腾讯云服务器（CentOS 7.6）</li></ul><p>首先创建一个 Spring Boot 工程，勾选 Web 依赖</p><p>完整  <code>pom.xml</code></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0&quot;</span> <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.2.6.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">relativePath</span>/&gt;</span> <span class="comment">&lt;!-- lookup parent from repository --&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>cn.imzjw.workflow.github<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>github-actions-springboot<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>0.0.1-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">name</span>&gt;</span>github-actions-springboot<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">description</span>&gt;</span>Demo project for Spring Boot<span class="tag">&lt;/<span class="name">description</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">properties</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">project.build.sourceEncoding</span>&gt;</span>UTF-8<span class="tag">&lt;/<span class="name">project.build.sourceEncoding</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">project.reporting.outputEncoding</span>&gt;</span>UTF-8<span class="tag">&lt;/<span class="name">project.reporting.outputEncoding</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">maven-surefire-plugin.version</span>&gt;</span>2.19.1<span class="tag">&lt;/<span class="name">maven-surefire-plugin.version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">java.version</span>&gt;</span>1.8<span class="tag">&lt;/<span class="name">java.version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">properties</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.2.6.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">executions</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">goals</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">goal</span>&gt;</span>build-info<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">goal</span>&gt;</span>repackage<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">executions</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"></span><br><span class="line">            <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.maven.plugins<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>maven-compiler-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.8.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"></span><br><span class="line">            <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.maven.plugins<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>maven-surefire-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;maven-surefire-plugin.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"></span><br><span class="line">            <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.codehaus.mojo<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>cobertura-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.7<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">formats</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">format</span>&gt;</span>html<span class="tag">&lt;/<span class="name">format</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">format</span>&gt;</span>xml<span class="tag">&lt;/<span class="name">format</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">formats</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">check</span>/&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure><p>新建一个类，用来测试</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ActionsController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;actions&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">actions</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;使用 GitHub Actions 部署至服务器&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>代码就这么点，然后就进行编写 actions 代码，在你项目的根目录下创建  <code>.github/workflows/main.yml</code></p><p>除了那俩文件夹名固定的，<code>main.yml</code>  文件名可以随便乱取。</p><p>我的项目结构</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d347d656/20210629162045.webp" alt="images"></p><p>编辑 main.yml 文件，添加如下配置</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">name:</span> <span class="string">Java</span> <span class="string">CI</span> <span class="string">with</span> <span class="string">Maven</span></span><br><span class="line"></span><br><span class="line"><span class="attr">on:</span></span><br><span class="line">  <span class="attr">push:</span></span><br><span class="line">    <span class="comment"># 分支</span></span><br><span class="line">    <span class="attr">branches:</span> [ <span class="string">master</span> ]</span><br><span class="line">  <span class="attr">pull_request:</span></span><br><span class="line">    <span class="attr">branches:</span> [ <span class="string">master</span> ]</span><br><span class="line"></span><br><span class="line"><span class="attr">jobs:</span></span><br><span class="line">  <span class="attr">compile:</span></span><br><span class="line">    <span class="attr">runs-on:</span> <span class="string">ubuntu-latest</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">Running</span> <span class="string">Java</span> <span class="string">$&#123;&#123;</span> <span class="string">matrix.java</span> <span class="string">&#125;&#125;</span> <span class="string">compile</span></span><br><span class="line">    <span class="attr">steps:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">uses:</span> <span class="string">actions/checkout@v2</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Set</span> <span class="string">up</span> <span class="string">JDK</span> <span class="number">1.8</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">actions/setup-java@v1</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">java-version:</span> <span class="number">1.8</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">缓存</span> <span class="string">Maven</span> <span class="string">依赖</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">actions/cache@v2</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">path:</span> <span class="string">~/.m2/repository</span></span><br><span class="line">          <span class="attr">key:</span> <span class="string">$&#123;&#123;</span> <span class="string">runner.os</span> <span class="string">&#125;&#125;-maven-$&#123;&#123;</span> <span class="string">hashFiles(&#x27;**/pom.xml&#x27;)</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">restore-keys:</span> <span class="string">|</span></span><br><span class="line"><span class="string">            $&#123;&#123; runner.os &#125;&#125;-maven-</span></span><br><span class="line"><span class="string"></span>      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">编译代码</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">mvn</span> <span class="string">compile</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Deploy</span> <span class="string">the</span> <span class="string">JAR</span> <span class="string">file</span> <span class="string">to</span> <span class="string">the</span> <span class="string">remote</span> <span class="string">server</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">actions/checkout@v2</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Set</span> <span class="string">up</span> <span class="string">JDK</span> <span class="number">1.8</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">actions/setup-java@v1</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">java-version:</span> <span class="number">1.8</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Generate</span> <span class="string">the</span> <span class="string">package</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">mvn</span> <span class="string">-B</span> <span class="string">package</span> <span class="string">--file</span> <span class="string">pom.xml</span> <span class="string">-Dmaven.test.skip=true</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">将</span> <span class="string">JAR</span> <span class="string">包部署到服务器</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">garygrossgarten/github-action-scp@release</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">local:</span> <span class="string">target/github-actions-springboot-0.0.1-SNAPSHOT.jar</span></span><br><span class="line">          <span class="attr">remote:</span> <span class="string">blog.imzjw.cn/actions/github-actions-springboot.jar</span></span><br><span class="line">          <span class="attr">host:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.HOST</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">username:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.SSH_USER</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">password:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.SSH_PASSWORD</span> <span class="string">&#125;&#125;</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">在服务器上执行</span> <span class="string">java</span> <span class="string">-jar，请确保服务器安装了</span> <span class="string">JDK</span></span><br><span class="line">        <span class="attr">if:</span> <span class="string">always()</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">fifsky/ssh-action@master</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">command:</span> <span class="string">|</span> <span class="comment"># 命令中的 &amp; 表示在后台运行进程</span></span><br><span class="line">            <span class="string">cd</span> <span class="string">blog.imzjw.cn/actions/</span> <span class="string">&amp;&amp;</span> <span class="string">java</span> <span class="string">-jar</span> <span class="string">github-actions-springboot.jar</span> <span class="string">&amp;</span></span><br><span class="line">          <span class="attr">host:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.HOST</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">user:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.SSH_USER</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">pass:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.SSH_PASSWORD</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">args:</span> <span class="string">&quot;-tt&quot;</span></span><br></pre></td></tr></table></figure><p>随后到 GitHub <a href="https://github.com/new">创建一个新的存储库</a> ，在仓库依次点击  <code>Setting -&gt; Secrets -&gt; New repository secret</code></p><p>三个密钥都必填 <font color="red">*</font></p><table><thead><tr><th align="center">Name</th><th align="center">Value</th></tr></thead><tbody><tr><td align="center">HOST</td><td align="center">填你的服务器 IP</td></tr><tr><td align="center">SSH_USER</td><td align="center">服务器用户名</td></tr><tr><td align="center">SSH_PASSWORD</td><td align="center">服务器密码</td></tr></tbody></table><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d347d656/20210629163537.webp" alt="images"></p><p>在这之前先检查一下服务器是否已安装 JDK，否则  <code>java -jar</code> 会失败</p><p><code>jdk-8u181-linux-x64.tar.gz</code>  下载地址</p><div class="btns rounded grid5">            <a class="button" href='https://repo.huaweicloud.com/java/jdk/8u181-b13/jdk-8u181-linux-x64.tar.gz' title='下载地址'><i class='fas fa-download'></i>下载地址</a>          </div><p>安装就不用说了…直接 tar 解压， vim /etc/profile 添加 JDK 路径， source /etc/profile 生效</p><p>最后直接 push 项目到 GitHub 存储仓中</p><p>点击仓库中的 Actions 可以看到已经跑起来了，点进去，可以看到每个步骤的工作流程！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d347d656/20210629164615.webp" alt="images"></p><p>设置的密钥都是安全加密的，duck 不必担心。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d347d656/20210629165106.webp" alt="images"></p><p>等待 Actions 工作完成之后，用 SSH 工具连接到你的服务器，执行</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps -ef | grep java</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d347d656/20210629165553.webp" alt="images"></p><p>完美！</p><p>最后浏览器访问 <code>http://IP:8080/actions</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d347d656/20210629165855.webp" alt="images"></p><p>参考：</p><ul><li><a href="https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#usage-limits">Workflow syntax for GitHub Actions</a></li></ul><p>感谢：</p><ul><li><p><a href="https://github.com/actions/setup-java">setup-java</a></p></li><li><p><a href="https://github.com/actions/cache">cache</a></p></li><li><p><a href="https://github.com/actions/checkout">checkout</a></p></li><li><p><a href="https://github.com/garygrossgarten/github-action-scp">github-action-scp</a></p></li><li><p><a href="https://github.com/fifsky/ssh-action">ssh-action</a></p></li></ul><p>本文 GitHub 仓库地址</p><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/sudojia/actions-deploy-springboot"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=sudojia&repo=actions-deploy-springboot&theme=vue&show_owner=true"/></a><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>我希望你喜欢这篇文章并学会了如何使用 GitHub Actions 来自动化（CI / CD Workflow）部署项目！</p>]]></content>
    
    
    <summary type="html">曾经我们部署 Spring Boot 项目的时候，还要手动 mvn clean install，然后再把 JAR 包上传到服务器，最后 java -jar，后面有了 jenkins CI 工具让我们一劳永逸</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring Boot" scheme="https://blog.imzjw.cn/tags/Spring-Boot/"/>
    
  </entry>
  
  <entry>
    <title>阿里云盘小白羊：支持 115 转存批量分享及下载</title>
    <link href="https://blog.imzjw.cn/posts/e9c3c84f/"/>
    <id>https://blog.imzjw.cn/posts/e9c3c84f/</id>
    <published>2021-06-08T05:00:18.000Z</published>
    <updated>2021-06-08T05:00:18.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>阿里云盘公测也有一段时间了，送容量的活动也出了不少，但是分享转存的功能一直迟迟未上线，有排等啦。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e9c3c84f/20210608114112.webp" alt="share"></p><p>在逛 GitHub 的时候，偶然发现了一款第三方阿里云盘：<strong>阿里云盘小白羊版！</strong></p><h2 id="阿里云盘小白羊版"><a href="#阿里云盘小白羊版" class="headerlink" title="阿里云盘小白羊版"></a>阿里云盘小白羊版</h2><p>目前仅支持 Windows 版，你可以完全把它当作阿里云盘官方客户端来使用，各方面都不输于官方版，由第三方小白羊制作，目前还在持续更新中。</p><div class="btns rounded grid5">            <a class="button" href='https://github.com/liupan1890/aliyunpan' title='GitHub 地址'><i class='fab fa-github'></i>GitHub 地址</a><a class="button" href='https://wwe.lanzoui.com/b01npsg8h' title='下载地址'><i class='fas fa-download'></i>下载地址</a>          </div><p>下载之后解压即可使用，非常的绿色，然后点击左上角进行登录，你可以选择阿里云盘 App 扫码登陆，也可以选择使用 <code>Cookie</code> 登录</p><p>登录成功之后，就会把云盘里的所有文件都给列出来，官方有的功能它都有，官方没的功能它也有</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e9c3c84f/20210608124131.webp" alt="images"></p><h2 id="特点"><a href="#特点" class="headerlink" title="特点"></a>特点</h2><p><strong>新建秒传链接</strong>（最大的特点）</p><p>相当于创建分享链接，你可以在网盘中任意选择一个或批量选择文件，然后点击<strong>新建秒传链</strong>，你可以对其设置密码，转存次数以及失效时间。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e9c3c84f/20210608125703.webp" alt="images"></p><p>点击创建短链接就会生成个短链，此后这个短链需在阿里云盘小白羊客户端使用。</p><p>就在客户端的根目录，点击<strong>导入秒传链</strong>，把人家分享的链接导入即可（亲测 1 G 以上的大文件都能秒导入）</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e9c3c84f/20210608130008.webp" alt="images"></p><p>此外，我们 115 网盘的秒传链接，也可以直接在这里导入</p><p>先安装油猴脚本<a href="https://greasyfork.org/zh-CN/scripts/413520-115-sha1%E8%BD%AC%E5%AD%98">【115 sha1 转存】</a>，然后获取 <strong>SHA1 链接</strong></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e9c3c84f/20210608132354.webp" alt="images"></p><p>并把获取的链接导入到阿里云盘小白羊版</p><div class="note warning flat"><p>作者说这个是靠运气的，并不是能百分百导入成功，也不是功能的问题，详见 <a href="https://github.com/liupan1890/aliyunpan/issues/11">Issues#11</a></p></div><p><strong>在线视频播放（这样就可以让你的朋友分享点学习资料并在线观影）</strong></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e9c3c84f/20210608125005.webp" alt="images"></p><p>以及图片也能在线预览</p><p>上传 \ 下载也能跑满宽带</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e9c3c84f/20210608113102.webp" alt="images"></p><h2 id="展望未来"><a href="#展望未来" class="headerlink" title="展望未来"></a>展望未来</h2><ul><li>Mac 客户端</li><li>离线下载<ol><li>可以自己一键配置离线服务器、使用公共离线服务器。实现电驴、磁力链接的下载</li><li>可以下载后自动上传到自己的网盘内</li></ol></li><li>文件加密、洗码功能<ol><li>可以对文件快速洗码（1 秒内），给文件生成新的 sha1 码，然后再上传到网盘（视频洗码后不影响在线预览）</li><li>可以对文件快速完整加密，加密后的文件无法预览，保护隐私（视频无法预览和截图，图片/文本/Doc/PDF 等文件无法在线预览）</li><li>可以对加密后的文件，快速解密恢复为原始文件</li></ol></li></ul><p>如果这些功能陆陆续续出了的话，也算的上是一款神器了！</p>]]></content>
    
    
    <summary type="html">阿里云盘公测也有一段时间了，送容量的活动也出了不少，但是分享转存的功能一直迟迟未上线，有排等啦。在逛 GitHub 的时候，偶然发现了一款第三方阿里云盘：阿里云盘小白羊版！</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="小白羊" scheme="https://blog.imzjw.cn/tags/%E5%B0%8F%E7%99%BD%E7%BE%8A/"/>
    
  </entry>
  
  <entry>
    <title>利用云函数每天自动推送天气</title>
    <link href="https://blog.imzjw.cn/posts/8419c5ed/"/>
    <id>https://blog.imzjw.cn/posts/8419c5ed/</id>
    <published>2021-05-23T03:30:09.000Z</published>
    <updated>2021-05-23T03:30:09.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前提准备"><a href="#前提准备" class="headerlink" title="前提准备"></a>前提准备</h2><p>腾讯云账号（需实名认证）</p><h2 id="创建函数"><a href="#创建函数" class="headerlink" title="创建函数"></a>创建函数</h2><p>前往<a href="https://console.cloud.tencent.com/scf/list-create?rid=4&ns=default&functionName=helloworld-1621741063&createType=empty">腾讯云函数</a> 新建函数，函数名称及地域随意，运行环境 Python 3.6 保持不变。</p><p>函数代码选择<strong>在线编辑</strong>，执行方法修改成 <code>index.main</code> （即把 <code>_handler</code> 给删掉）随后粘贴如下代码</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/python3</span></span><br><span class="line"><span class="comment">#coding=utf-8</span></span><br><span class="line"> </span><br><span class="line"><span class="keyword">import</span> requests, json</span><br><span class="line"> </span><br><span class="line">spkey = <span class="string">&#x27;f0612538bbxxxxxxxxxxxxxx&#x27;</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_iciba_everyday</span>():</span><br><span class="line">    icbapi = <span class="string">&#x27;http://open.iciba.com/dsapi/&#x27;</span></span><br><span class="line">    eed = requests.get(icbapi)</span><br><span class="line">    bee = eed.json()  <span class="comment">#返回的数据</span></span><br><span class="line">    english = bee[<span class="string">&#x27;content&#x27;</span>]</span><br><span class="line">    zh_CN = bee[<span class="string">&#x27;note&#x27;</span>]</span><br><span class="line">    <span class="built_in">str</span> = <span class="string">&#x27;【奇怪的知识】\n&#x27;</span> + english + <span class="string">&#x27;\n&#x27;</span> + zh_CN</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">str</span></span><br><span class="line"> </span><br><span class="line"><span class="keyword">def</span> <span class="title function_">main</span>(<span class="params">arg1,arg2</span>):</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        api = <span class="string">&#x27;http://t.weather.itboy.net/api/weather/city/&#x27;</span>             <span class="comment">#API地址，必须配合城市代码使用</span></span><br><span class="line">        city_code = <span class="string">&#x27;101280601&#x27;</span></span><br><span class="line">        tqurl = api + city_code</span><br><span class="line">        response = requests.get(tqurl)</span><br><span class="line">        d = response.json()         <span class="comment">#将数据以json形式返回，这个d就是返回的json数据</span></span><br><span class="line">        <span class="keyword">if</span>(d[<span class="string">&#x27;status&#x27;</span>] == <span class="number">200</span>):     <span class="comment">#当返回状态码为200，输出天气状况</span></span><br><span class="line">            parent = d[<span class="string">&quot;cityInfo&quot;</span>][<span class="string">&quot;parent&quot;</span>] <span class="comment">#省</span></span><br><span class="line">            city = d[<span class="string">&quot;cityInfo&quot;</span>][<span class="string">&quot;city&quot;</span>] <span class="comment">#市</span></span><br><span class="line">            update_time = d[<span class="string">&quot;time&quot;</span>] <span class="comment">#更新时间</span></span><br><span class="line">            date = d[<span class="string">&quot;data&quot;</span>][<span class="string">&quot;forecast&quot;</span>][<span class="number">0</span>][<span class="string">&quot;ymd&quot;</span>] <span class="comment">#日期</span></span><br><span class="line">            week = d[<span class="string">&quot;data&quot;</span>][<span class="string">&quot;forecast&quot;</span>][<span class="number">0</span>][<span class="string">&quot;week&quot;</span>] <span class="comment">#星期</span></span><br><span class="line">            weather_type = d[<span class="string">&quot;data&quot;</span>][<span class="string">&quot;forecast&quot;</span>][<span class="number">0</span>][<span class="string">&quot;type&quot;</span>] <span class="comment"># 天气</span></span><br><span class="line">            wendu_high = d[<span class="string">&quot;data&quot;</span>][<span class="string">&quot;forecast&quot;</span>][<span class="number">0</span>][<span class="string">&quot;high&quot;</span>] <span class="comment">#最高温度</span></span><br><span class="line">            wendu_low = d[<span class="string">&quot;data&quot;</span>][<span class="string">&quot;forecast&quot;</span>][<span class="number">0</span>][<span class="string">&quot;low&quot;</span>] <span class="comment">#最低温度</span></span><br><span class="line">            shidu = d[<span class="string">&quot;data&quot;</span>][<span class="string">&quot;shidu&quot;</span>] <span class="comment">#湿度</span></span><br><span class="line">            pm25 = <span class="built_in">str</span>(d[<span class="string">&quot;data&quot;</span>][<span class="string">&quot;pm25&quot;</span>]) <span class="comment">#PM2.5</span></span><br><span class="line">            pm10 = <span class="built_in">str</span>(d[<span class="string">&quot;data&quot;</span>][<span class="string">&quot;pm10&quot;</span>]) <span class="comment">#PM10</span></span><br><span class="line">            quality = d[<span class="string">&quot;data&quot;</span>][<span class="string">&quot;quality&quot;</span>] <span class="comment">#天气质量</span></span><br><span class="line">            fx = d[<span class="string">&quot;data&quot;</span>][<span class="string">&quot;forecast&quot;</span>][<span class="number">0</span>][<span class="string">&quot;fx&quot;</span>] <span class="comment">#风向</span></span><br><span class="line">            fl = d[<span class="string">&quot;data&quot;</span>][<span class="string">&quot;forecast&quot;</span>][<span class="number">0</span>][<span class="string">&quot;fl&quot;</span>] <span class="comment">#风力</span></span><br><span class="line">            ganmao = d[<span class="string">&quot;data&quot;</span>][<span class="string">&quot;ganmao&quot;</span>] <span class="comment">#感冒指数</span></span><br><span class="line">            tips = d[<span class="string">&quot;data&quot;</span>][<span class="string">&quot;forecast&quot;</span>][<span class="number">0</span>][<span class="string">&quot;notice&quot;</span>] <span class="comment">#温馨提示</span></span><br><span class="line">            cpurl = <span class="string">&#x27;https://qmsg.zendee.cn/send/&#x27;</span>+spkey</span><br><span class="line">            <span class="comment"># 天气提示内容</span></span><br><span class="line">            tdwt = get_iciba_everyday()  + <span class="string">&quot;\n-----------------------------------------&quot;</span> + <span class="string">&quot;\n【今日份天气】\n城市： &quot;</span> + parent + city + \</span><br><span class="line">                   <span class="string">&quot;\n日期： &quot;</span> + date + <span class="string">&quot;\n星期: &quot;</span> + week + <span class="string">&quot;\n天气: &quot;</span> + weather_type + <span class="string">&quot;\n温度: &quot;</span> + wendu_high + <span class="string">&quot; / &quot;</span>+ wendu_low + <span class="string">&quot;\n湿度: &quot;</span> + \</span><br><span class="line">                    shidu + <span class="string">&quot;\nPM25: &quot;</span> + pm25 + <span class="string">&quot;\nPM10: &quot;</span> + pm10 + <span class="string">&quot;\n空气质量: &quot;</span> + quality + \</span><br><span class="line">                   <span class="string">&quot;\n风力风向: &quot;</span> + fx + fl + <span class="string">&quot;\n感冒指数: &quot;</span>  + ganmao + <span class="string">&quot;\n温馨提示： &quot;</span> + tips + <span class="string">&quot;\n更新时间: &quot;</span> + update_time</span><br><span class="line">            <span class="built_in">print</span>(tdwt)</span><br><span class="line">            data = &#123;</span><br><span class="line">                <span class="string">&#x27;msg&#x27;</span>:tdwt.encode(<span class="string">&#x27;utf-8&#x27;</span>)</span><br><span class="line">            &#125;</span><br><span class="line">            requests.post(cpurl,data=data)         <span class="comment">#把天气数据转换成UTF-8格式，不然要报错。</span></span><br><span class="line">    <span class="keyword">except</span>:</span><br><span class="line">        error = <span class="string">&#x27;【出现错误】\n　　今日天气推送错误，请检查服务或网络状态！&#x27;</span></span><br><span class="line">        <span class="built_in">print</span>(error)</span><br></pre></td></tr></table></figure><p>展开<strong>高级配置</strong>，内存选择 64 MB 即可。</p><p>前往 <a href="https://qmsg.zendee.cn/">https://qmsg.zendee.cn</a> 注册账号，获取 key，然后在 QQ 内添加给你推送的服务号，修改函数代码中第 6 行的 <code>spkey</code>，修改成你的 key</p><p>前往 <a href="https://where.qweather.com/index.html">https://where.qweather.com/index.html</a> 输入期望要推送的城市天气，比如深圳，复制该 ID，修改函数代码中第 19 行的 <code>city_code</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8419c5ed/8jashda.webp" alt="images"></p><p>修改函数代码中第 19 行的 <code>cpurl</code> 默认是推送到个人的，如需推送到群消息，请将 <code>url</code> 修改为 <code>https://qmsg.zendee.cn/group/</code></p><p>最后点击测试，如提示<strong>检测到您的函数未部署，是否将当前函数部署并测试？</strong>选择<strong>是</strong>，稍后即可在 QQ 查看内容。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8419c5ed/20210523120651.webp" alt="images"></p><h2 id="定时触发"><a href="#定时触发" class="headerlink" title="定时触发"></a>定时触发</h2><p>点击<strong>触发管理</strong>，创建一个触发器</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8419c5ed/20210523122605.webp" alt="images"></p><p>将会在每天早晨的 7 : 30 分进行推送</p><p>代码贡献者 <a href="https://www.52pojie.cn/home.php?mod=space&uid=894296">@culprit</a></p>]]></content>
    
    
    <summary type="html">准备腾讯云账号（需实名认证）前往腾讯云函数新建函数，函数名称及地域随意，运行环境 Python 3.6 保持不变。函数代码选择在线编辑，执行方法修改成 index.main（即把 _handler 给删掉）</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="云函数" scheme="https://blog.imzjw.cn/tags/%E4%BA%91%E5%87%BD%E6%95%B0/"/>
    
  </entry>
  
  <entry>
    <title>使用 MX 解析记录挂载域名后缀到临时邮箱平台</title>
    <link href="https://blog.imzjw.cn/posts/mx-mail/"/>
    <id>https://blog.imzjw.cn/posts/mx-mail/</id>
    <published>2021-05-13T05:56:57.000Z</published>
    <updated>2021-05-13T05:56:57.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>有时候，在网站上注册账号，不想用自己的邮箱，想用临时邮箱，而现在网上的临时邮箱后缀大多可能已经被加入了黑名单，所以我们可以用 Freenom 白嫖到的免费域名，来挂载到临时邮箱平台。</p><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>首先我们要准备一枚主域名，白嫖 Freenom 域名可看 <a href="https://blog.imzjw.cn/posts/rdp-freenom/">【利用 Google RDP 免费注册 Freenom 域名】</a></p><p>进入临时邮箱网站： <a class="btn-beautify pink" href="http://www.yopmail.com/"   title="Yopmail"><i class="far fa-hand-point-right"></i><span>Yopmail</span></a></p><p>点击新增域名</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/mx-mail/addDomain.6ce206v2ark0.webp" alt="addDomain"></p><p>输入自己的域名之后前往域名商进行解析</p><table><thead><tr><th align="center">第一种</th><th align="center">第二种</th></tr></thead><tbody><tr><td align="center">MX 记录解析到 <code>smtp.yopmail.com.</code> 优先级为 <strong>1</strong></td><td align="center">直接 A 记录解析到  <strong>87.98.164.155</strong></td></tr></tbody></table><p>然后点击 “Check domain name” 检查一下解析记录是否生效，如图即添加成功！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/mx-mail/bbss.5mf1ht3l40o0.webp" alt="images"></p><p>随后返回首页，随意输入邮箱前缀，进入邮箱</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/mx-mail/s22.3268sw04cnq0.webp" alt="images"></p><p>测试下能否收到邮箱，邮箱后缀注意是刚刚添加的域名。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/mx-mail/ghh.3w1gyzgg3v60.webp" alt="images"></p><p>成功收到邮箱。需要注意的是，虽然邮箱后缀显示的是 <code>yopmail.com</code>，我们不用理会它，因为它会自行转发的，这也是为什么，那些 piao Office 365、OD 5T 的，因为 <code>ncov.office.gy</code> 这个域名已经添加进去了。不过现在好像 piao 不了了。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/mx-mail/asd22.22g0bygjd5c0.webp" alt="images"></p><p>不仅 yopmail 这个平台，还有 Jaz Mail，反正能添加自己域名的临时邮箱的，解析一下，那都可以收到邮箱。</p>]]></content>
    
    
    <summary type="html">有时候，在网站上注册账号，不想用自己的邮箱，想用临时邮箱，而现在网上的临时邮箱后缀大多可能已经被加入了黑名单，所以我们可以用 Freenom 白嫖到的免费域名，来挂载到临时邮箱平台。</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="临时邮箱" scheme="https://blog.imzjw.cn/tags/%E4%B8%B4%E6%97%B6%E9%82%AE%E7%AE%B1/"/>
    
  </entry>
  
  <entry>
    <title>解决腾讯云服务器无法下载安装宝塔插件</title>
    <link href="https://blog.imzjw.cn/posts/589d224b/"/>
    <id>https://blog.imzjw.cn/posts/589d224b/</id>
    <published>2021-05-04T14:00:41.000Z</published>
    <updated>2021-05-04T14:00:41.000Z</updated>
    
    <content type="html"><![CDATA[<p>这个问题也是我今晚才遇到的，买了服务器快三个月了，啥也没动，空空的，就在今晚，打开 FinalShell 连接到服务器，执行</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install -y wget &amp;&amp; wget -O install.sh http://download.bt.cn/install/install_6.0.sh &amp;&amp; sh install.sh</span><br></pre></td></tr></table></figure><p>哦吼！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/589d224b/images.5s35nza9zvs0.webp" alt="images"></p><p>然后我就一步一步排查，可以看到能发送请求到宝塔，说明服务器本身是能够访问外网的，我也通过 <code>curl https://blog.imzjw.cn</code> 证实了！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/589d224b/images2222.7980mt83dro0.webp" alt="curl"></p><p>继续尝试，在那条安装命令中 <code>http://download.bt.cn/install/install_6.0.sh</code> 在本机上能下载，然后尝试在服务器上 <code>ping download.bt.cn</code>，结果不通，那就可以排除不是服务器的问题，我顿时就很纳闷啊。最后在<a href="https://www.bt.cn/bbs/">宝塔论坛</a>里找到了我的答案。原文：<a href="https://www.bt.cn/bbs/thread-30579-1-1.html">指定 host</a></p><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><p>国内的服务器执行任意一条命令即可（其它的参考上面的原文）</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;113.107.111.78 download.bt.cn&#x27;</span> &gt;&gt; /etc/hosts</span><br></pre></td></tr></table></figure><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;123.129.198.197 download.bt.cn&#x27;</span> &gt;&gt; /etc/hosts</span><br></pre></td></tr></table></figure><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;120.206.184.160 download.bt.cn&#x27;</span> &gt;&gt; /etc/hosts</span><br></pre></td></tr></table></figure><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;119.188.210.21 download.bt.cn&#x27;</span> &gt;&gt; /etc/hosts</span><br></pre></td></tr></table></figure><p>最后再执行</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install -y wget &amp;&amp; wget -O install.sh http://download.bt.cn/install/install_6.0.sh &amp;&amp; sh install.sh</span><br></pre></td></tr></table></figure><p>成功安装</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/589d224b/bbsd.5a2a2d823as0.webp" alt="images"></p>]]></content>
    
    
    <summary type="html">这个问题也是我今晚才遇到的，买了服务器快三个月了，啥也没动，空空的，就在今晚，打开 FinalShell 连接到服务器，执行 yum install -y wget &amp;&amp; wget -O install.sh http://...哦吼！</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="宝塔面板" scheme="https://blog.imzjw.cn/tags/%E5%AE%9D%E5%A1%94%E9%9D%A2%E6%9D%BF/"/>
    
  </entry>
  
  <entry>
    <title>Hexo + Butterfly 使用各大 CDN 服务商加速网站</title>
    <link href="https://blog.imzjw.cn/posts/hexocdn/"/>
    <id>https://blog.imzjw.cn/posts/hexocdn/</id>
    <published>2021-05-01T11:46:29.000Z</published>
    <updated>2021-05-04T11:30:00.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>如果一个网站打开半天加载不出来，或者加载极其之慢，那对于用户来说体验不是很好，可能还会直接 <kbd>CTRL</kbd> + <kbd>W</kbd> 走人！</p><p>所以我们可以对网站进行优化一下，最后再来套上 CDN 服务！</p><p>首先咱们先对静态资源调教一番！</p><h2 id="静态资源压缩"><a href="#静态资源压缩" class="headerlink" title="静态资源压缩"></a>静态资源压缩</h2><p>可以前往 <a href="https://blog.imzjw.cn/posts/b74f504f/#gulp-%E5%8E%8B%E7%BC%A9">Gulp 压缩</a> 配置</p><h2 id="CDN-公共库"><a href="#CDN-公共库" class="headerlink" title="CDN 公共库"></a>CDN 公共库</h2><p>像静态资源（js、css、json、xml、img..等）这些，我们可以使用公共库进行加速</p><ul><li><a href="https://www.jsdelivr.com/">jsDelivr</a>：国内外都有节点，也是本站主题 Butterfly 首选的公共库！前端常用的库也有</li><li><a href="https://www.bootcdn.cn/">BootCDN</a>：只有国内节点</li><li><a href="https://cdnjs.com/">cdnjs</a>：国外的公共库，用的是 Cloudflare</li><li>还有其它的，但是推荐使用 <code>jsDelivr</code>，可以加速我们自己的静态文件！</li></ul><h3 id="CDN-公共库如何使用"><a href="#CDN-公共库如何使用" class="headerlink" title="CDN 公共库如何使用"></a>CDN 公共库如何使用</h3><p>参考 <a href="https://blog.imzjw.cn/posts/speed-jsdelivr/">使用 jsDelivr 加速静态文件</a></p><p>另外，如果是 Butterfly 主题的话，在配置文件中找到 <code>main_css</code> 、<code>main</code>、<code>utils</code>、<code>local_search\algolia_js</code>、<code>translate</code>，默认是采用本地加载，我们也可以使用 <code>jsDelivr</code></p><p>例如：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 非必要請不要修改</span></span><br><span class="line"><span class="attr">CDN:</span></span><br><span class="line">  <span class="comment"># main</span></span><br><span class="line">  <span class="attr">main_css:</span> <span class="string">https://cdn.jsdelivr.net/gh/zjwo/zjwo.github.io/css/index.css</span></span><br><span class="line">  <span class="comment"># main_css: /css/index.css # 4000 用</span></span><br><span class="line">  <span class="attr">main:</span> <span class="string">https://cdn.jsdelivr.net/gh/zjwo/zjwo.github.io/js/main.js</span></span><br><span class="line">  <span class="attr">utils:</span> <span class="string">https://cdn.jsdelivr.net/gh/zjwo/zjwo.github.io/js/utils.js</span></span><br><span class="line">  </span><br><span class="line">  <span class="string">...</span></span><br><span class="line">  <span class="attr">local_search:</span> <span class="string">https://cdn.jsdelivr.net/gh/zjwo/zjwo.github.io/js/search/local-search.js</span></span><br><span class="line">  </span><br><span class="line">  <span class="string">...</span></span><br><span class="line">  <span class="attr">translate:</span> <span class="string">https://cdn.jsdelivr.net/gh/zjwo/zjwo.github.io/js/tw_cn.js</span></span><br></pre></td></tr></table></figure><p>这样就能实现全站 CDN 啦！</p><p>但是 <code>jsDelivr</code> 又有缓存问题，会导致无法在第一时间更新。但是我们可以强刷呀！如果你是使用 GitHub Actions 的话，在你的 Actions 脚本最后加上如下代码，这样当我们持续部署博客的时候，又帮我们刷新了 jsd 的缓存问题！</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Purge</span> <span class="string">JsDelivr</span> <span class="string">CDN</span></span><br><span class="line">  <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">    # 注意替换成你的 jsd 地址</span></span><br><span class="line"><span class="string">    curl https://purge.jsdelivr.net/gh/zjwo/zjwo.github.io/css/index.css</span></span><br><span class="line"><span class="string">    curl https://purge.jsdelivr.net/gh/zjwo/zjwo.github.io/js/main.js</span></span><br><span class="line"><span class="string">    curl https://purge.jsdelivr.net/gh/zjwo/zjwo.github.io/js/utils.js</span></span><br><span class="line"><span class="string">    curl https://purge.jsdelivr.net/gh/zjwo/zjwo.github.io/js/tw_cn.js</span></span><br><span class="line"><span class="string">    curl https://purge.jsdelivr.net/gh/zjwo/zjwo.github.io/js/search/local-search.js</span></span><br></pre></td></tr></table></figure><h2 id="静态资源异步加载"><a href="#静态资源异步加载" class="headerlink" title="静态资源异步加载"></a>静态资源异步加载</h2><p>参考 <a href="https://akilar.top/posts/615d5ede/">Hexo 异步加载方案</a>，无非就是给 js 脚本加上 <code>defer</code> 和 <code>ansyc</code> 属性来实现异步加载，例如：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">bottom:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">&lt;script</span> <span class="string">defer</span> <span class="string">https://npm.elemecdn.com/vue@2.6.11&quot;&gt;&lt;/script&gt;</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">&lt;script</span> <span class="string">async</span> <span class="string">src=&quot;https://cdn.jsdelivr.net/gh/zjwo/CDN/js/pyq/pyq.min.js&quot;&gt;&lt;/script&gt;</span></span><br></pre></td></tr></table></figure><p>css 也能异步加载</p><p>最后再给网站套上 CDN 服务！</p><div class="note danger flat"><p>注：以下操作都必须实名认证且域名备案！</p></div><div class="note warning flat"><p>本文只讲又拍云、百度云加速、多吉云的配置方法，其它云服务厂商大同小异！</p></div><h2 id="又拍云加速"><a href="#又拍云加速" class="headerlink" title="又拍云加速"></a>又拍云加速</h2><p>免费获取每月 10 GB 存储空间 + 15 GB 流量，前提你得加入又拍云联盟。然后得到代金券（67￥/ 年）</p><p>但是又拍云从去年开始就改了规则！如图</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/images.2d4bb8gkw63o.webp" alt="images"></p><p>首先注册<a href="https://console.upyun.com/register/">又拍云</a>，实名认证成功之后再申请加入<a href="https://www.upyun.com/league">又拍云联盟</a></p><p>申请又拍云联盟的步骤官网也写的很清楚，照着做就是了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/lianmeng.3egn5ol57sy0.webp" alt="images"></p><p>第二步那个页脚 LOGO，如果你是 Butterfly 主题的话，可以直接在主题的配置文件找到 <code>custom_text</code> 并加入以下代码</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">custom_text:</span> <span class="string">&lt;a</span> <span class="string">href=&quot;https://www.upyun.com/?utm_source=lianmeng&amp;utm_medium=referral&quot;</span> <span class="string">target=&quot;_blank&quot;</span> <span class="string">rel=&quot;noopener</span> <span class="string">nofollow&quot;&gt;&lt;img</span> <span class="string">style=&quot;position:relative;top:-2.5px;&quot;</span> <span class="string">src=&quot;https://cdn.jsdelivr.net/gh/caibhh/CDN/img/blog/%E5%8F%88%E6%8B%8D%E4%BA%91_logo5.webp&quot;</span> <span class="string">align=&quot;absmiddle&quot;</span> <span class="string">width=&quot;60px&quot;</span> <span class="string">height=&quot;30px&quot;&gt;提供加速服务&lt;/a&gt;</span></span><br></pre></td></tr></table></figure><p>数天过后会有邮件通知你成功加入又拍云联盟，67￥ / 年的代金券也发放下来了，接着我们就开始创建一个 CDN 服务</p><p>进入 <a href="https://console.upyun.com/services/cdn/">CDN 服务管理</a>，点击创建服务！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/upyunconfig.4lr8a2r70sg0.webp" alt="images"></p><p>最后点击创建</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/gss.24j1e9nw3bls.webp" alt="images"></p><p>复制该 <code>CNAME</code> 值，到你的域名服务商进行解析</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/jiexi.4zkdhoi60180.webp" alt="解析"></p><p>打开 CMD PING 一下网站，CDN 生效了！<img no-lazy class="inline" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/happy.1lp0kadh0ds0.webp" style="height:90px;"/></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/cmd.5ctxb0x1dos0.webp" alt="cmd"></p><p>然后你兴奋的打开网站，哦吼！<img no-lazy class="inline" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/ghw.23jao2ookxts.webp" style="height:90px;"/></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/oh.56qg5sa3xq40.webp" alt="哦吼"></p><p>害，这是因为证书的问题啦！<img no-lazy class="inline" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/222.40kx6hpl55c0.webp" style="height:90px;"/></p><p>进入功能配置，选择 HTTPS，添加自有证书，最后可以勾上强制 HTTPS 访问，过一会即可正常打开网站！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/https.26xoqhurzj28.webp" alt="https"></p><h3 id="其它配置"><a href="#其它配置" class="headerlink" title="其它配置"></a>其它配置</h3><p><strong>缓存控制</strong></p><ul><li>就开启了分段缓存和离线模式</li></ul><p><strong>性能优化</strong></p><ul><li>智能压缩（GZip 和 Brotli 我都开启了，等级都为 3 级）但是要注意，当客户端同时支持 Gzip 和 Brotli 算法的情况下，Brotli 的优先级高于 Gzip。</li><li>页面压缩，开启</li><li>重定向跟随，开启</li></ul><p><strong>HTTPS</strong></p><ul><li>TLS 1.3，开启</li><li>最低 TLS 版本，我选的 <code>1.0</code></li><li>HTTP/2，开启</li></ul><p><strong>访问控制（重要）</strong></p><ul><li><p>IP 黑白名单，建议大家把以下 IP 都加入到<strong>黑名单</strong>里</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">117.136.14.181</span><br><span class="line">117.183.0.241</span><br><span class="line">171.106.203.19</span><br><span class="line">220.173.125.83</span><br><span class="line">222.217.145.185</span><br><span class="line">113.14.130.128</span><br><span class="line">222.83.150.92</span><br><span class="line">113.14.130.19</span><br><span class="line">113.14.130.73</span><br><span class="line">113.57.53.37</span><br></pre></td></tr></table></figure></li><li><p>IP 访问限制，开启</p><p>点击添加限制规则，资源路径：<code>/*</code>，限制策略：100 - 200 禁止 600 秒，200 - 500 禁止 3600 秒，500 以上 86400 秒</p></li><li><p>CC 防护，开启</p><p>URI 匹配规则：<code>/*</code>，访问频率阈值：200 次，智能防护</p></li><li><p>WAF 保护，开启</p></li></ul><p>又拍云配置成功！</p><h2 id="百度云加速"><a href="#百度云加速" class="headerlink" title="百度云加速"></a>百度云加速</h2><p>呼，百度云加速作为中国站的 Cloudflare，免费流量 10 GB / 天，基本来说完全够用了，但是免费版的速度嘛，不是很理想！</p><p>首先<a href="https://passport.baidu.com/v2/?reg&tpl=websec&u=https://su.baidu.com?login_type=passport">注册</a>百度账号，然后<a href="https://su.baidu.com/home/login/https%3A%2F%2Fsu.baidu.com%2F">登录</a>进入之后进行实名认证，百度的实名认证有所不同，是手持身份证进行认证的，审核成功之后，进入控制台，添加网站。</p><p>注意这里要输入主域名并切换为 <code>CNAME</code> 接入方式！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/addsite.2hfzhm73qsk0.webp" alt="addsite"></p><p>第二步就是添加加速域名了，最后点击保存，下一步！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/save.4eb0i7gz4um0.webp" alt="images"></p><p>第三步进行解析</p><p>第四步成功！</p><p>配置证书，在证书管理下的证书列表，上传证书即可</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/ssl.g7m1a9okia8.webp" alt="ssl"></p><p>最后在安全功能中找到 HTTPS，设置为全程加密！</p><h3 id="其它配置-1"><a href="#其它配置-1" class="headerlink" title="其它配置"></a>其它配置</h3><p>CDN 加速选项，开启 IPV6 访问</p><p>然后…其实百度云加速也没什么好配置的，防护功能默认都给你开了。</p><p>有需求的可以在特定页面规则自己定制规则。</p><p>百度云加速教程就到这了！</p><h2 id="多吉云融合-CDN"><a href="#多吉云融合-CDN" class="headerlink" title="多吉云融合 CDN"></a>多吉云融合 CDN</h2><p>多吉云是在 <a href="https://www.hin.cool/">W4J1e’s blog</a> 偶然发现的，节点很多，一开始以为是多吉搜索家的呢，结果不是。</p><p>多吉云的融合 CDN 每月免费流量 20 GB，云存储 10 GB。</p><p>融合 CDN 是个啥？</p><p>简单来说就是把大厂的 CDN 节点整合到了一起，从节点的质量上来说没有太大的区别。大厂的品牌更可靠一些，融合的话好处在于如果某个大厂出问题了，可以随时切换，不会对公司的业务产生什么影响。参考 <a href="https://zhidao.baidu.com/question/1995378707094027867.html?qbl=relate_question_0&word=%EF%BF%BD%DA%BA%EF%BF%BDCDN%EF%BF%BD%EF%BF%BD%CA%B2%C3%B4">融合 CDN 是什么，跟 CDN 有什么不同？</a></p><p>注册登录<a href="https://console.dogecloud.com/register.html">多吉云</a>，然后进行实名认证（支持支付宝一键认证）</p><p>说明一下，多吉云的实名认证不是强制性的，只是实名认证了有免费额度 20 GB / 月，你不想实名的话可以选择付费滴！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/greergreer.2fwjtk0r0knw.webp" alt="images"></p><p>融合 CDN 的价格确实比较便宜！</p><p>认证成功之后最上方点击<a href="https://console.dogecloud.com/cdn/list">融合 CDN</a>，然后添加域名</p><ul><li>加速域名：就是你要加速的域名</li><li>业务类型：Web 访问、静态资源、小文件、M3U8</li><li>服务地域：我选的中国境内，因为我境外解析到了 GitHub</li><li>源站类型：IP \ 域名都行</li><li>回源协议：看你源站是啥协议呗！</li><li>回源 Host：他说可以为空，我就留空了</li><li>确定添加</li></ul><p>等待它部署五分钟之后，状态成功了，进行解析它提供的 <code>CNAME</code></p><h3 id="其它配置-2"><a href="#其它配置-2" class="headerlink" title="其它配置"></a>其它配置</h3><p><strong>基本配置</strong></p><ul><li>IPv6 访问，开启</li></ul><p><strong>回源设置</strong></p><ul><li>回源跳转跟随，开启回源跟随 301、302</li></ul><p><strong>访问控制</strong></p><ul><li><p>IP 黑白名单（还是一样，建议大家把以下 IP 都加入到黑名单中）</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">117.136.14.181</span><br><span class="line">117.183.0.241</span><br><span class="line">171.106.203.19</span><br><span class="line">220.173.125.83</span><br><span class="line">222.217.145.185</span><br><span class="line">113.14.130.128</span><br><span class="line">222.83.150.92</span><br><span class="line">113.14.130.19</span><br><span class="line">113.14.130.73</span><br><span class="line">113.57.53.37</span><br></pre></td></tr></table></figure></li><li><p>带宽流量封顶，这个看个人吧，我设置的 5 分钟内流量超过 5 GB 就解析回源！</p></li></ul><p><strong>性能优化</strong></p><ul><li>开启 GZip 压缩</li></ul><p><strong>HTTPS 配置</strong></p><ul><li><p>最后还是一样，上传证书</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/ssl.87pbjpl2p6k.webp" alt="ssl"></p><p>开启强制跳转 HTTPS，跳转方式 301，这肯定 301 永久啊</p></li></ul><p>PING 一下瞅瞅融合 CDN 的延迟。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/ping.53g6yygbj440.webp" alt="ping"></p><p>我觉得 <img no-lazy class="inline" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/ky.o4keqqe741c.webp" style="height:100px;"/></p><p>但也有缺点，就是每更改一个配置项，都要重新部署！另外还有如果你的站点更新了或者发布了一篇文章，都要去<a href="https://console.dogecloud.com/cdn/refresh">刷新预热</a>一下！问了下客服，目前暂时也没什么自动刷新的脚本或者 API，但是速度是真的可以，也值得了，况且博客平时更新也不勤！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/danteng.z1tyhfmi4og.webp" alt="images"></p><hr><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/aaa.6qf6c5643rk0.webp" alt="images"></p><h2 id="多-IP-解析"><a href="#多-IP-解析" class="headerlink" title="多 IP 解析"></a>多 IP 解析</h2><p>昨晚试了多种方案，在 <a href="https://www.ping.cn/">Ping.cn</a> 和 <a href="http://ping.chinaz.com/">站长工具</a> 都看了下，我是没看出什么区别，我是真看不出来，反正最后解析方案，我默认解析到了又拍云，移动解析百度云加速，电信解析到多吉云，如有更好的方案可以在下方评论留言，感谢！ <img no-lazy class="inline" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexocdn/thn.5mrxumbtbhs0.webp" style="height:75px;"/></p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><table><thead><tr><th>服务商</th><th>免费流量</th><th>HTTPS</th><th>速度</th><th>稳定性</th><th>实名认证</th><th>客服</th></tr></thead><tbody><tr><td>又拍云</td><td>15 GB / 月</td><td>免费</td><td>A</td><td>稳</td><td>支付宝一键认证 \ 手持身份证</td><td>人工 \ 工单</td></tr><tr><td>百度云加速</td><td>10 GB / 天</td><td>免费</td><td>B</td><td>稳</td><td>手持身份证</td><td>工单 \ 机器人</td></tr><tr><td>多吉云</td><td>20 GB / 月</td><td>免费</td><td>A</td><td>稳</td><td>支付宝一键认证 \ 手持身份证</td><td>人工</td></tr></tbody></table><p>又拍云<a href="https://www.upyun.com/price_instruction/">计费说明</a></p><p>多吉云<a href="https://www.dogecloud.com/price?product=cdn">计费说明</a></p><p>百度云加速<a href="https://su.baidu.com/help/index.html#/10_changjianwenti/0_HIDE_FAQ/23_CDNliuliangdejisuanfangshishuoming.md">计算方式说明</a></p>]]></content>
    
    
    <summary type="html">如果一个网站打开半天加载不出来，或者加载极其之慢，那对于用户来说体验不是很好，可能还会直接 CTRL + W 走人！所以我们可以对网站进行优化一下，最后再来套 CDN 服务！</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/tags/Hexo/"/>
    
    <category term="CDN" scheme="https://blog.imzjw.cn/tags/CDN/"/>
    
  </entry>
  
  <entry>
    <title>本人自用 Hexo-Butterfly 主题参考手册</title>
    <link href="https://blog.imzjw.cn/posts/bfdocs/"/>
    <id>https://blog.imzjw.cn/posts/bfdocs/</id>
    <published>2021-04-30T03:21:36.000Z</published>
    <updated>2021-12-12T03:12:29.000Z</updated>
    
    <content type="html"><![CDATA[<p>原生 Butterfly 主题不支持部分标签外挂，若想使用，参考 <a href="https://akilar.top/posts/615e2dec/">Tag Plugins Plus</a></p><h2 id="Front-matter"><a href="#Front-matter" class="headerlink" title="Front-matter"></a>Front-matter</h2><p>Front-matter 是文件最上方以 <code>---</code> 分隔的区域</p><table><thead><tr><th align="center">写法</th><th align="center">解释</th></tr></thead><tbody><tr><td align="center">title</td><td align="center">【必需】页面标题</td></tr><tr><td align="center">date</td><td align="center">【必需】页面创建日期</td></tr><tr><td align="center">type</td><td align="center">【必需】标籤、分类和友情链接三个页面需要配置</td></tr><tr><td align="center">updated</td><td align="center">【可选】页面更新日期</td></tr><tr><td align="center">description</td><td align="center">【可选】页面描述</td></tr><tr><td align="center">keywords</td><td align="center">【可选】页面关键字</td></tr><tr><td align="center">comments</td><td align="center">【可选】显示页面评论模块 (默认 true)</td></tr><tr><td align="center">top_img</td><td align="center">【可选】页面顶部图片</td></tr><tr><td align="center">mathjax</td><td align="center">【可选】显示 mathjax (当设置 mathjax 的 per_page: false 时，才需要配置，默认 false)</td></tr><tr><td align="center">katex</td><td align="center">【可选】显示 katex (当设置 katex 的 per_page: false 时，才需要配置，默认 false)</td></tr><tr><td align="center">aside</td><td align="center">【可选】显示侧边栏 (默认 true)</td></tr><tr><td align="center">aplayer</td><td align="center">【可选】在需要的页面加载 aplayer 的 js 和 css, 请参考文章下面的<code>音乐</code> 配置</td></tr><tr><td align="center">highlight_shrink</td><td align="center">【可选】配置代码框是否展开 (true/false)(默认为设置中 highlight_shrink 的配置)</td></tr></tbody></table><h2 id="Post-Front-matter"><a href="#Post-Front-matter" class="headerlink" title="Post Front-matter"></a>Post Front-matter</h2><table><thead><tr><th align="center">写法</th><th align="center">解释</th></tr></thead><tbody><tr><td align="center">title</td><td align="center">【必需】文章標題</td></tr><tr><td align="center">date</td><td align="center">【必需】文章創建日期</td></tr><tr><td align="center">updated</td><td align="center">【可選】文章更新日期</td></tr><tr><td align="center">tags</td><td align="center">【可選】文章標籤</td></tr><tr><td align="center">categories</td><td align="center">【可選】文章分類</td></tr><tr><td align="center">keywords</td><td align="center">【可選】文章關鍵字</td></tr><tr><td align="center">description</td><td align="center">【可選】文章描述</td></tr><tr><td align="center">top_img</td><td align="center">【可選】文章頂部圖片</td></tr><tr><td align="center">cover</td><td align="center">【可選】文章縮略圖(如果沒有設置top_img,文章頁頂部將顯示縮略圖，可設為false/圖片地址/留空)</td></tr><tr><td align="center">comments</td><td align="center">【可選】顯示文章評論模塊(默認 true)</td></tr><tr><td align="center">toc</td><td align="center">【可選】顯示文章TOC(默認為設置中toc的enable配置)</td></tr><tr><td align="center">toc_number</td><td align="center">【可選】顯示toc_number(默認為設置中toc的number配置)</td></tr><tr><td align="center">copyright</td><td align="center">【可選】顯示文章版權模塊(默認為設置中post_copyright的enable配置)</td></tr><tr><td align="center">copyright_author</td><td align="center">【可選】文章版權模塊的<code>文章作者</code></td></tr><tr><td align="center">copyright_author_href</td><td align="center">【可選】文章版權模塊的<code>文章作者</code>鏈接</td></tr><tr><td align="center">copyright_url</td><td align="center">【可選】文章版權模塊的<code>文章連結</code>鏈接</td></tr><tr><td align="center">copyright_info</td><td align="center">【可選】文章版權模塊的<code>版權聲明</code>文字</td></tr><tr><td align="center">mathjax</td><td align="center">【可選】顯示 mathjax (當設置 mathjax 的 per_page: false時，才需要配置，默認 false)</td></tr><tr><td align="center">katex</td><td align="center">【可選】顯示 katex (當設置 katex 的 per_page: false 時，才需要配置，默認 false)</td></tr><tr><td align="center">aplayer</td><td align="center">【可選】在需要的頁面加載 aplayer 的 js 和 css</td></tr><tr><td align="center">highlight_shrink</td><td align="center">【可選】配置代碼框是否展開(true/false)(默認為設置中highlight_shrink的配置)</td></tr><tr><td align="center">aside</td><td align="center">【可選】顯示側邊欄 (默認 true)</td></tr></tbody></table><h2 id="标签外挂"><a href="#标签外挂" class="headerlink" title="标签外挂"></a>标签外挂</h2><p>标签外挂是 Hexo 独有的功能，并不是标准的 Markdown 格式。</p><h3 id="Note"><a href="#Note" class="headerlink" title="Note"></a>Note</h3><div class="tabs" id="simple"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="simple-1">simple</button><button type="button" class="tab " data-href="simple-2">modern</button><button type="button" class="tab " data-href="simple-3">flat</button><button type="button" class="tab " data-href="simple-4">disabled</button><button type="button" class="tab " data-href="simple-5">no-icon</button></ul><div class="tab-contents"><div class="tab-item-content active" id="simple-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note simple %&#125;</span><br><span class="line">默认 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note default simple %&#125;</span><br><span class="line">default 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note primary simple %&#125;</span><br><span class="line">primary 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note success simple %&#125;</span><br><span class="line">success 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note info simple %&#125;</span><br><span class="line">info 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note warning simple %&#125;</span><br><span class="line">warning 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note danger simple %&#125;</span><br><span class="line">danger 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><div class="note simple"><p>默认 提示块标签</p></div><div class="note default simple"><p>default 提示块标签</p></div><div class="note primary simple"><p>primary 提示块标签</p></div><div class="note success simple"><p>success 提示块标签</p></div><div class="note info simple"><p>info 提示块标签</p></div><div class="note warning simple"><p>warning 提示块标签</p></div><div class="note danger simple"><p>danger 提示块标签</p></div></div><div class="tab-item-content" id="simple-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note modern %&#125;</span><br><span class="line">默认 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note default modern %&#125;</span><br><span class="line">default 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note primary modern %&#125;</span><br><span class="line">primary 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note success modern %&#125;</span><br><span class="line">success 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note info modern %&#125;</span><br><span class="line">info 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note warning modern %&#125;</span><br><span class="line">warning 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note danger modern %&#125;</span><br><span class="line">danger 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><div class="note modern"><p>默认 提示块标签</p></div><div class="note default modern"><p>default 提示块标签</p></div><div class="note primary modern"><p>primary 提示块标签</p></div><div class="note success modern"><p>success 提示块标签</p></div><div class="note info modern"><p>info 提示块标签</p></div><div class="note warning modern"><p>warning 提示块标签</p></div><div class="note danger modern"><p>danger 提示块标签</p></div></div><div class="tab-item-content" id="simple-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note flat %&#125;</span><br><span class="line">默认 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note default flat %&#125;</span><br><span class="line">default 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note primary flat %&#125;</span><br><span class="line">primary 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note success flat %&#125;</span><br><span class="line">success 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note info flat %&#125;</span><br><span class="line">info 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note warning flat %&#125;</span><br><span class="line">warning 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note danger flat %&#125;</span><br><span class="line">danger 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><div class="note flat"><p>默认 提示块标签</p></div><div class="note default flat"><p>default 提示块标签</p></div><div class="note primary flat"><p>primary 提示块标签</p></div><div class="note success flat"><p>success 提示块标签</p></div><div class="note info flat"><p>info 提示块标签</p></div><div class="note warning flat"><p>warning 提示块标签</p></div><div class="note danger flat"><p>danger 提示块标签</p></div></div><div class="tab-item-content" id="simple-4"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note disabled %&#125;</span><br><span class="line">默认 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note default disabled %&#125;</span><br><span class="line">default 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note primary disabled %&#125;</span><br><span class="line">primary 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note success disabled %&#125;</span><br><span class="line">success 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note info disabled %&#125;</span><br><span class="line">info 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note warning disabled %&#125;</span><br><span class="line">warning 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note danger disabled %&#125;</span><br><span class="line">danger 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><div class="note disabled"><p>默认 提示块标签</p></div><div class="note default disabled"><p>default 提示块标签</p></div><div class="note primary disabled"><p>primary 提示块标签</p></div><div class="note success disabled"><p>success 提示块标签</p></div><div class="note info disabled"><p>info 提示块标签</p></div><div class="note warning disabled"><p>warning 提示块标签</p></div><div class="note danger disabled"><p>danger 提示块标签</p></div></div><div class="tab-item-content" id="simple-5"><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note no-icon %&#125;</span><br><span class="line">默认 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note default no-icon %&#125;</span><br><span class="line">default 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note primary no-icon %&#125;</span><br><span class="line">primary 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note success no-icon %&#125;</span><br><span class="line">success 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note info no-icon %&#125;</span><br><span class="line">info 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note warning no-icon %&#125;</span><br><span class="line">warning 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note danger no-icon %&#125;</span><br><span class="line">danger 提示块标签</span><br><span class="line">&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><div class="note no-icon flat"><p>默认 提示块标签</p></div><div class="note default no-icon flat"><p>default 提示块标签</p></div><div class="note primary no-icon flat"><p>primary 提示块标签</p></div><div class="note success no-icon flat"><p>success 提示块标签</p></div><div class="note info no-icon flat"><p>info 提示块标签</p></div><div class="note warning no-icon flat"><p>warning 提示块标签</p></div><div class="note danger no-icon flat"><p>danger 提示块标签</p></div></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><p>自定义 <code>icon</code></p><div class="tabs" id="simple"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="simple-1">simple</button><button type="button" class="tab " data-href="simple-2">modern</button><button type="button" class="tab " data-href="simple-3">flat</button><button type="button" class="tab " data-href="simple-4">disabled</button><button type="button" class="tab " data-href="simple-5">no-icon</button></ul><div class="tab-contents"><div class="tab-item-content active" id="simple-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note &#x27;fab fa-cc-visa&#x27; simple %&#125;</span><br><span class="line">你是刷 Visa 还是是 UnionPay</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note red &#x27;fas fa-bullhorn&#x27; simple %&#125;</span><br><span class="line">2021年快到了....</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note pink &#x27;fas fa-car-crash&#x27; simple %&#125;</span><br><span class="line">小心开车 安全至上</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note green &#x27;fas fa-fan&#x27; simple%&#125;</span><br><span class="line">这是三片呢？还是四片？</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note orange &#x27;fas fa-battery-half&#x27; simple %&#125;</span><br><span class="line">该充电了哦！</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note purple &#x27;far fa-hand-scissors&#x27; simple %&#125;</span><br><span class="line">剪刀石頭布</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note blue &#x27;fab fa-internet-explorer&#x27; simple %&#125;</span><br><span class="line">前端最討厭的瀏覽器</span><br><span class="line">&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><div class="note icon-padding simple"><i class="note-icon fab fa-cc-visa"></i><p>你是刷 Visa 还是是 UnionPay</p></div><div class="note red icon-padding simple"><i class="note-icon fas fa-bullhorn"></i><p>2022 年快到了….</p></div><div class="note pink icon-padding simple"><i class="note-icon fas fa-car-crash"></i><p>小心开车 安全至上</p></div><div class="note green icon-padding simple"><i class="note-icon fas fa-fan"></i><p>这是三片呢？还是四片？</p></div><div class="note orange icon-padding simple"><i class="note-icon fas fa-battery-half"></i><p>该充电了哦！</p></div><div class="note purple icon-padding simple"><i class="note-icon far fa-hand-scissors"></i><p>剪刀石頭布</p></div><div class="note blue icon-padding simple"><i class="note-icon fab fa-internet-explorer"></i><p>前端最討厭的瀏覽器</p></div></div><div class="tab-item-content" id="simple-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note &#x27;fab fa-cc-visa&#x27; modern %&#125;</span><br><span class="line">你是刷 Visa 还是是 UnionPay</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note red &#x27;fas fa-bullhorn&#x27; modern %&#125;</span><br><span class="line">2021年快到了....</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note pink &#x27;fas fa-car-crash&#x27; modern %&#125;</span><br><span class="line">小心开车 安全至上</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note green &#x27;fas fa-fan&#x27; modern%&#125;</span><br><span class="line">这是三片呢？还是四片？</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note orange &#x27;fas fa-battery-half&#x27; modern %&#125;</span><br><span class="line">该充电了哦！</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note purple &#x27;far fa-hand-scissors&#x27; modern %&#125;</span><br><span class="line">剪刀石頭布</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note blue &#x27;fab fa-internet-explorer&#x27; modern %&#125;</span><br><span class="line">前端最討厭的瀏覽器</span><br><span class="line">&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><div class="note icon-padding modern"><i class="note-icon fab fa-cc-visa"></i><p>你是刷 Visa 还是是 UnionPay</p></div><div class="note red icon-padding modern"><i class="note-icon fas fa-bullhorn"></i><p>2021年快到了….</p></div><div class="note pink icon-padding modern"><i class="note-icon fas fa-car-crash"></i><p>小心开车 安全至上</p></div><div class="note green icon-padding modern"><i class="note-icon fas fa-fan"></i><p>这是三片呢？还是四片？</p></div><div class="note orange icon-padding modern"><i class="note-icon fas fa-battery-half"></i><p>该充电了哦！</p></div><div class="note purple icon-padding modern"><i class="note-icon far fa-hand-scissors"></i><p>剪刀石頭布</p></div><div class="note blue icon-padding modern"><i class="note-icon fab fa-internet-explorer"></i><p>前端最討厭的瀏覽器</p></div></div><div class="tab-item-content" id="simple-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note &#x27;fab fa-cc-visa&#x27; flat %&#125;</span><br><span class="line">你是刷 Visa 还是是 UnionPay</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note red &#x27;fas fa-bullhorn&#x27; flat %&#125;</span><br><span class="line">2021年快到了....</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note pink &#x27;fas fa-car-crash&#x27; flat %&#125;</span><br><span class="line">小心开车 安全至上</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note green &#x27;fas fa-fan&#x27; flat%&#125;</span><br><span class="line">这是三片呢？还是四片？</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note orange &#x27;fas fa-battery-half&#x27; flat %&#125;</span><br><span class="line">该充电了哦！</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note purple &#x27;far fa-hand-scissors&#x27; flat %&#125;</span><br><span class="line">剪刀石頭布</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note blue &#x27;fab fa-internet-explorer&#x27; flat %&#125;</span><br><span class="line">前端最討厭的瀏覽器</span><br><span class="line">&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><div class="note icon-padding flat"><i class="note-icon fab fa-cc-visa"></i><p>你是刷 Visa 还是是 UnionPay</p></div><div class="note red icon-padding flat"><i class="note-icon fas fa-bullhorn"></i><p>2021年快到了….</p></div><div class="note pink icon-padding flat"><i class="note-icon fas fa-car-crash"></i><p>小心开车 安全至上</p></div><div class="note green icon-padding flat"><i class="note-icon fas fa-fan"></i><p>这是三片呢？还是四片？</p></div><div class="note orange icon-padding flat"><i class="note-icon fas fa-battery-half"></i><p>该充电了哦！</p></div><div class="note purple icon-padding flat"><i class="note-icon far fa-hand-scissors"></i><p>剪刀石頭布</p></div><div class="note blue icon-padding flat"><i class="note-icon fab fa-internet-explorer"></i><p>前端最討厭的瀏覽器</p></div></div><div class="tab-item-content" id="simple-4"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note &#x27;fab fa-cc-visa&#x27; disabled  %&#125;</span><br><span class="line">你是刷 Visa 还是是 UnionPay</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note red &#x27;fas fa-bullhorn&#x27; disabled  %&#125;</span><br><span class="line">2021年快到了....</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note pink &#x27;fas fa-car-crash&#x27; disabled  %&#125;</span><br><span class="line">小心开车 安全至上</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note green &#x27;fas fa-fan&#x27; disabled %&#125;</span><br><span class="line">这是三片呢？还是四片？</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note orange &#x27;fas fa-battery-half&#x27; disabled  %&#125;</span><br><span class="line">该充电了哦！</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note purple &#x27;far fa-hand-scissors&#x27; disabled  %&#125;</span><br><span class="line">剪刀石頭布</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note blue &#x27;fab fa-internet-explorer&#x27; disabled  %&#125;</span><br><span class="line">前端最討厭的瀏覽器</span><br><span class="line">&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><div class="note icon-padding disabled"><i class="note-icon fab fa-cc-visa"></i><p>你是刷 Visa 还是是 UnionPay</p></div><div class="note red icon-padding disabled"><i class="note-icon fas fa-bullhorn"></i><p>2021年快到了….</p></div><div class="note pink icon-padding disabled"><i class="note-icon fas fa-car-crash"></i><p>小心开车 安全至上</p></div><div class="note green icon-padding disabled"><i class="note-icon fas fa-fan"></i><p>这是三片呢？还是四片？</p></div><div class="note orange icon-padding disabled"><i class="note-icon fas fa-battery-half"></i><p>该充电了哦！</p></div><div class="note purple icon-padding disabled"><i class="note-icon far fa-hand-scissors"></i><p>剪刀石頭布</p></div><div class="note blue icon-padding disabled"><i class="note-icon fab fa-internet-explorer"></i><p>前端最討厭的瀏覽器</p></div></div><div class="tab-item-content" id="simple-5"><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note no-icon %&#125;</span><br><span class="line">你是刷 Visa 还是 UnionPay</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note blue no-icon %&#125;</span><br><span class="line">2021年快到了....</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note pink no-icon %&#125;</span><br><span class="line">小心开车 安全至上</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note red no-icon %&#125;</span><br><span class="line">这是三片呢？还是四片？</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note orange no-icon %&#125;</span><br><span class="line">你是刷 Visa 还是 UnionPay</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note purple no-icon %&#125;</span><br><span class="line">剪刀石头布</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line">&#123;% note green no-icon %&#125;</span><br><span class="line">前端最讨厌的浏览器</span><br><span class="line">&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><div class="note no-icon flat"><p>你是刷 Visa 还是 UnionPay</p></div><div class="note blue no-icon flat"><p>2021年快到了….</p></div><div class="note pink no-icon flat"><p>小心开车 安全至上</p></div><div class="note red no-icon flat"><p>这是三片呢？还是四片？</p></div><div class="note orange no-icon flat"><p>你是刷 Visa 还是 UnionPay</p></div><div class="note purple no-icon flat"><p>剪刀石头布</p></div><div class="note green no-icon flat"><p>前端最讨厌的浏览器</p></div></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="小标签及边框颜色"><a href="#小标签及边框颜色" class="headerlink" title="小标签及边框颜色"></a>小标签及边框颜色</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">class</span>=<span class="string">&quot;inline-tag red&quot;</span>&gt;</span>红色小标签<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">class</span>=<span class="string">&quot;inline-tag green&quot;</span>&gt;</span>绿色小标签<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">class</span>=<span class="string">&quot;inline-tag blue&quot;</span>&gt;</span>蓝色小标签<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">class</span>=<span class="string">&quot;inline-tag yellow&quot;</span>&gt;</span>黄色小标签<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">class</span>=<span class="string">&quot;inline-tag grey&quot;</span>&gt;</span>灰色小标签<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br></pre></td></tr></table></figure><p><span class="inline-tag red">红色小标签</span> <span class="inline-tag green">绿色小标签</span> <span class="inline-tag blue">蓝色小标签</span> <span class="inline-tag yellow">黄色小标签</span> <span class="inline-tag grey">灰色小标签</span></p><p><strong>小标签自定义颜色</strong></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">span</span> <span class="attr">class</span>=<span class="string">&quot;inline-tag&quot;</span> <span class="attr">style</span>=<span class="string">&quot;--Color:#881B12&quot;</span>&gt;</span>自定义颜色小标签<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br></pre></td></tr></table></figure><p><strong>边框颜色</strong></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;div-border [left|right|top|bottom] [red|green|blue|yellow|grey]&quot;</span>&gt;</span></span><br><span class="line">  语法</span><br><span class="line"><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;div-border top red&quot;</span>&gt;</span>上边框<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;div-border right red&quot;</span>&gt;</span>右边框<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;div-border bottom red&quot;</span>&gt;</span>下边框<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;div-border left red&quot;</span>&gt;</span>左边框<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br></pre></td></tr></table></figure><p class="div-border top red">上边框</p><p class="div-border right red">右边框</p><p class="div-border bottom red">下边框</p><p class="div-border left red">左边框</p><p><strong>边框自定义颜色</strong></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;div-border left style=&quot;</span><span class="attr">--Color:</span>#<span class="attr">881B12</span>&quot;&quot;&gt;</span>左边框<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="全边框及自定义颜色"><a href="#全边框及自定义颜色" class="headerlink" title="全边框及自定义颜色"></a>全边框及自定义颜色</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;div-border&quot;</span> <span class="attr">style</span>=<span class="string">&quot;background-color: rgba(82,196,26,.1);border: 1px solid #52c41a;border-radius: 0.4rem;&quot;</span>&gt;</span></span><br><span class="line">  全边框</span><br><span class="line"><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">/* 或者如下写法 */</span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">style</span>=<span class="string">&quot;background-color: rgba(82,196,26,.1);border: 1px solid #52c41a;border-radius: 0.4rem;display: block;padding: 10px;&quot;</span>&gt;</span></span><br><span class="line">  全边框</span><br><span class="line"><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">/* 内置样式 */</span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;div-border green&quot;</span>&gt;</span>绿色<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;div-border red&quot;</span>&gt;</span>红色<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;div-border yellow&quot;</span>&gt;</span>黄色<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;div-border grey&quot;</span>&gt;</span>灰色<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;div-border blue&quot;</span>&gt;</span>蓝色<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br></pre></td></tr></table></figure><p class="div-border" style="background-color: rgba(82,196,26,.1);border: 1px solid #52c41a;border-radius: 0.4rem;">全边框</p><p style="background-color: rgba(82,196,26,.1);border: 1px solid #52c41a;border-radius: 0.4rem;display: block;padding: 10px;">全边框</p><p class="div-border green">绿色</p><p class="div-border red">红色</p><p class="div-border yellow">黄色</p><p class="div-border grey">灰色</p><p class="div-border blue">蓝色</p><h3 id="上标标签-tip"><a href="#上标标签-tip" class="headerlink" title="上标标签 tip"></a>上标标签 tip</h3><div class="tabs" id="tip"><ul class="nav-tabs"><button type="button" class="tab " data-href="tip-1">标签语法</button><button type="button" class="tab " data-href="tip-2">配置参数</button><button type="button" class="tab  active" data-href="tip-3">样式预览</button><button type="button" class="tab " data-href="tip-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="tip-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip [参数，可选] %&#125;文本内容&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="tip-2"><ol><li>样式：success、error、warning、bolt、ban、home、sync、cogs、key、bell</li><li>自定义图标：支持 fontawesome。</li></ol></div><div class="tab-item-content active" id="tip-3"><div class="tip "><p>默认情况</p></div>   <div class="tip success"><p>success</p></div>   <div class="tip error"><p>error</p></div>   <div class="tip warning"><p>warning</p></div>   <div class="tip bolt"><p>bolt</p></div>   <div class="tip ban"><p>ban</p></div>   <div class="tip home"><p>home</p></div>   <div class="tip sync"><p>sync</p></div>   <div class="tip cogs"><p>cogs</p></div>   <div class="tip key"><p>key</p></div>   <div class="tip bell"><p>bell</p></div>   <div class="tip fa-atom"><p>自定义font awesome图标</p></div></div><div class="tab-item-content" id="tip-4"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip %&#125;默认情况&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip success %&#125;success&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip error %&#125;error&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip warning %&#125;warning&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip bolt %&#125;bolt&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip ban %&#125;ban&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip home %&#125;home&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip sync %&#125;sync&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip cogs %&#125;cogs&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip key %&#125;key&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip bell %&#125;bell&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip fa-atom %&#125;自定义font awesome图标&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="动态标签-anima"><a href="#动态标签-anima" class="headerlink" title="动态标签 anima"></a>动态标签 anima</h3><div class="tabs" id="tip"><ul class="nav-tabs"><button type="button" class="tab " data-href="tip-1">标签语法</button><button type="button" class="tab " data-href="tip-2">配置参数</button><button type="button" class="tab  active" data-href="tip-3">样式预览</button><button type="button" class="tab " data-href="tip-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="tip-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip [参数，可选] %&#125;文本内容&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="tip-2"><div class="note blue icon-padding simple"><i class="note-icon fas fa-bullhorn"></i><p>更多详情请参看 <a href="http://l-lin.github.io/font-awesome-animation/">font-awesome-animation文档</a></p><ol><li>将所需的CSS类添加到图标（或DOM中的任何元素）。</li><li>对于父级悬停样式，需要给目标元素添加指定CSS类，同时还要给目标元素的父级元素添加CSS类<code>faa-parent animated-hover</code>。（详情见示例及示例源码）<br>You can regulate the speed of the animation by adding the CSS class or . faa-fastfaa-slow</li><li>可以通过给目标元素添加CSS类<code>faa-fast</code>或<code>faa-slow</code>来控制动画快慢。</li></ol></div><table><thead><tr><th align="left">On DOM load<br>当页面加载时<br>显示动画</th><th align="left">On hover<br>当鼠标悬停时<br>显示动画</th><th align="left">On parent hover<br>当鼠标悬停<br>在父级元素时<br>显示动画</th></tr></thead><tbody><tr><td align="left"><span><i class="fas fa-wrench faa-wrench animated"></i>&nbsp;faa-wrench animated</span></td><td align="left"><span><i class="fas fa-wrench faa-wrench animated-hover"></i>&nbsp;faa-wrench animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-wrench faa-wrench"></i>&nbsp;faa-wrench</span></td></tr><tr><td align="left"><span><i class="fas fa-bell faa-ring animated"></i>&nbsp;faa-ring animated</span></td><td align="left"><span><i class="fas fa-bell faa-ring animated-hover"></i>&nbsp;faa-ring animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-bell faa-ring"></i>&nbsp;faa-ring</span></td></tr><tr><td align="left"><span><i class="fas fa-envelope faa-horizontal animated"></i>&nbsp;faa-horizontal animated</span></td><td align="left"><span><i class="fas fa-envelope faa-horizontal animated-hover"></i>&nbsp;faa-horizontal animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-envelope faa-horizontal"></i>&nbsp;faa-horizontal</span></td></tr><tr><td align="left"><span><i class="fas fa-thumbs-up faa-vertical animated"></i>&nbsp;faa-vertical animated</span></td><td align="left"><span><i class="fas fa-thumbs-up faa-vertical animated-hover"></i>&nbsp;faa-vertical animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-thumbs-up faa-vertical"></i>&nbsp;faa-vertical</span></td></tr><tr><td align="left"><span><i class="fas fa-exclamation-triangle faa-flash animated"></i>&nbsp;faa-flash animated</span></td><td align="left"><span><i class="fas fa-exclamation-triangle faa-flash animated-hover"></i>&nbsp;faa-flash animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-exclamation-triangle faa-flash"></i>&nbsp;faa-flash</span></td></tr><tr><td align="left"><span><i class="fas fa-thumbs-up faa-bounce animated"></i>&nbsp;faa-bounce animated</span></td><td align="left"><span><i class="fas fa-thumbs-up faa-bounce animated-hover"></i>&nbsp;faa-bounce animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-thumbs-up faa-bounce"></i>&nbsp;faa-bounce</span></td></tr><tr><td align="left"><span><i class="fas fa-spinner faa-spin animated"></i>&nbsp;faa-spin animated</span></td><td align="left"><span><i class="fas fa-spinner faa-spin animated-hover"></i>&nbsp;faa-spin animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-spinner faa-spin"></i>&nbsp;faa-spin</span></td></tr><tr><td align="left"><span><i class="fas fa-plane faa-tada animated"></i>&nbsp;faa-tada animated</span></td><td align="left"><span><i class="fas fa-plane faa-tada animated-hover"></i>&nbsp;faa-tada animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-plane faa-tada"></i>&nbsp;faa-tada</span></td></tr><tr><td align="left"><span><i class="fas fa-heart faa-pulse animated"></i>&nbsp;faa-pulse animated</span></td><td align="left"><span><i class="fas fa-heart faa-pulse animated-hover"></i>&nbsp;faa-pulse animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-heart faa-pulse"></i>&nbsp;faa-pulse</span></td></tr><tr><td align="left"><span><i class="fas fa-envelope faa-shake animated"></i>&nbsp;faa-shake animated</span></td><td align="left"><span><i class="fas fa-envelope faa-shake animated-hover"></i>&nbsp;faa-shake animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-envelope faa-shake"></i>&nbsp;faa-shake</span></td></tr><tr><td align="left"><span><i class="fas fa-trophy faa-tada animated"></i>&nbsp;faa-tada animated</span></td><td align="left"><span><i class="fas fa-trophy faa-tada animated-hover"></i>&nbsp;faa-tada animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-trophy faa-tada"></i>&nbsp;faa-tada</span></td></tr><tr><td align="left"><span><i class="fas fa-space-shuttle faa-passing animated"></i>&nbsp;faa-passing animated</span></td><td align="left"><span><i class="fas fa-space-shuttle faa-passing animated-hover"></i>&nbsp;faa-passing animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-space-shuttle faa-passing"></i>&nbsp;faa-passing</span></td></tr><tr><td align="left"><span><i class="fas fa-space-shuttle faa-passing-reverse animated"></i>&nbsp;faa-passing-reverse animated</span></td><td align="left"><span><i class="fas fa-space-shuttle faa-passing-reverse animated-hover"></i>&nbsp;faa-passing-reverse animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-space-shuttle faa-passing-reverse"></i>&nbsp;faa-passing-reverse</span></td></tr><tr><td align="left"><span><i class="fas fa-circle faa-burst animated"></i>&nbsp;faa-burst animated</span></td><td align="left"><span><i class="fas fa-circle faa-burst animated-hover"></i>&nbsp;faa-burst animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-circle faa-burst"></i>&nbsp;faa-burst</span></td></tr><tr><td align="left"><span><i class="fas fa-star faa-falling animated"></i>&nbsp;faa-falling animated</span></td><td align="left"><span><i class="fas fa-star faa-falling animated-hover"></i>&nbsp;faa-falling animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-star faa-falling"></i>&nbsp;faa-falling</span></td></tr><tr><td align="left"><span><i class="fas fa-rocket faa-rising animated"></i>&nbsp;faa-rising animated</span></td><td align="left"><span><i class="fas fa-rocket faa-rising animated-hover"></i>&nbsp;faa-rising animated-hover</span></td><td align="left"><span class="faa-parent animated-hover"><i class="fas fa-rocket faa-rising"></i>&nbsp;faa-rising</span></td></tr></tbody></table></div><div class="tab-item-content active" id="tip-3"><ol><li><p>On DOM load（当页面加载时显示动画）</p><div class="tip warning faa-horizontal animated"><p>warning</p></div><div class="tip ban faa-flash animated"><p>ban</p></div></li><li><p>调整动画速度。</p><div class="tip warning faa-horizontal animated faa-fast"><p>warning</p></div><div class="tip ban faa-flash animated faa-slow"><p>ban</p></div></li><li><p>On hover（当鼠标悬停时显示动画）</p><div class="tip warning faa-horizontal animated-hover"><p>warning</p></div><div class="tip ban faa-flash animated-hover"><p>ban</p></div></li><li><p>On parent hover（当鼠标悬停在父级元素时显示动画）</p><div class="tip warning faa-parent animated-hover"><p class="faa-horizontal">warning</p></div><div class="tip ban faa-parent animated-hover"><p class="faa-flash">ban</p></div></li></ol></div><div class="tab-item-content" id="tip-4"><ol><li><p>On DOM load（当页面加载时显示动画）</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip warning faa-horizontal animated %&#125;warning&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip ban faa-flash animated %&#125;ban&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure></li><li><p>调整动画速度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip warning faa-horizontal animated faa-fast %&#125;warning&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip ban faa-flash animated faa-slow %&#125;ban&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure></li><li><p>On hover（当鼠标悬停时显示动画）</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip warning faa-horizontal animated-hover %&#125;warning&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip ban faa-flash animated-hover %&#125;ban&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure></li><li><p>On parent hover（当鼠标悬停在父级元素时显示动画）</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip warning faa-parent animated-hover %&#125;<span class="language-xml"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;faa-horizontal&quot;</span>&gt;</span></span>warning<span class="language-xml"><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span>&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip ban faa-parent animated-hover %&#125;<span class="language-xml"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;faa-flash&quot;</span>&gt;</span></span>ban<span class="language-xml"><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span>&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure></li></ol></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="复选列表-checkbox"><a href="#复选列表-checkbox" class="headerlink" title="复选列表 checkbox"></a>复选列表 checkbox</h3><div class="tabs" id="checkbox"><ul class="nav-tabs"><button type="button" class="tab " data-href="checkbox-1">标签语法</button><button type="button" class="tab " data-href="checkbox-2">配置参数</button><button type="button" class="tab  active" data-href="checkbox-3">样式预览</button><button type="button" class="tab " data-href="checkbox-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="checkbox-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% checkbox 样式参数（可选）, 文本（支持简单md） %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="checkbox-2"><ol><li>样式: plus, minus, times</li><li>颜色: <span class='p red'>red</span>,<span class='p yellow'>yellow</span>,<span class='p green'>green</span>,<span class='p cyan'>cyan</span>,<span class='p blue'>blue</span>,<span class='p gray'>gray</span></li><li>选中状态: checked</li></ol></div><div class="tab-item-content active" id="checkbox-3"><div class='checkbox'><input type="checkbox" />            <p>纯文本测试</p>            </div>   <div class='checkbox checked'><input type="checkbox" checked="checked"/>            <p>支持简单的 <a href="https://guides.github.com/features/mastering-markdown/">markdown</a> 语法</p>            </div>   <div class='checkbox red'><input type="checkbox" />            <p>支持自定义颜色</p>            </div>   <div class='checkbox green checked'><input type="checkbox" checked="checked"/>            <p>绿色 + 默认选中</p>            </div>   <div class='checkbox yellow checked'><input type="checkbox" checked="checked"/>            <p>黄色 + 默认选中</p>            </div>   <div class='checkbox cyan checked'><input type="checkbox" checked="checked"/>            <p>青色 + 默认选中</p>            </div>   <div class='checkbox blue checked'><input type="checkbox" checked="checked"/>            <p>蓝色 + 默认选中</p>            </div>   <div class='checkbox plus green checked'><input type="checkbox" checked="checked"/>            <p>增加</p>            </div>   <div class='checkbox minus yellow checked'><input type="checkbox" checked="checked"/>            <p>减少</p>            </div>   <div class='checkbox times red checked'><input type="checkbox" checked="checked"/>            <p>叉</p>            </div></div><div class="tab-item-content" id="checkbox-4"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&#123;% checkbox 纯文本测试 %&#125;</span><br><span class="line">&#123;% checkbox checked, 支持简单的 [<span class="string">markdown</span>](<span class="link">https://guides.github.com/features/mastering-markdown/</span>) 语法 %&#125;</span><br><span class="line">&#123;% checkbox red, 支持自定义颜色 %&#125;</span><br><span class="line">&#123;% checkbox green checked, 绿色 + 默认选中 %&#125;</span><br><span class="line">&#123;% checkbox yellow checked, 黄色 + 默认选中 %&#125;</span><br><span class="line">&#123;% checkbox cyan checked, 青色 + 默认选中 %&#125;</span><br><span class="line">&#123;% checkbox blue checked, 蓝色 + 默认选中 %&#125;</span><br><span class="line">&#123;% checkbox plus green checked, 增加 %&#125;</span><br><span class="line">&#123;% checkbox minus yellow checked, 减少 %&#125;</span><br><span class="line">&#123;% checkbox times red checked, 叉 %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="单选列表-radio"><a href="#单选列表-radio" class="headerlink" title="单选列表 radio"></a>单选列表 radio</h3><div class="tabs" id="radio"><ul class="nav-tabs"><button type="button" class="tab " data-href="radio-1">标签语法</button><button type="button" class="tab " data-href="radio-2">配置参数</button><button type="button" class="tab  active" data-href="radio-3">样式预览</button><button type="button" class="tab " data-href="radio-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="radio-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% radio 样式参数（可选）, 文本（支持简单md） %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="radio-2"><ol><li>颜色: <span class='p red'>red</span>,<span class='p yellow'>yellow</span>,<span class='p green'>green</span>,<span class='p cyan'>cyan</span>,<span class='p blue'>blue</span>,<span class='p gray'>gray</span></li><li>选中状态: checked</li></ol></div><div class="tab-item-content active" id="radio-3"><div class='checkbox'><input type="radio" />            <p>纯文本测试</p>            </div>   <div class='checkbox checked'><input type="radio" checked="checked"/>            <p>支持简单的 <a href="https://guides.github.com/features/mastering-markdown/">markdown</a> 语法</p>            </div>   <div class='checkbox red'><input type="radio" />            <p>支持自定义颜色</p>            </div>   <div class='checkbox green'><input type="radio" />            <p>绿色</p>            </div>   <div class='checkbox yellow'><input type="radio" />            <p>黄色</p>            </div>   <div class='checkbox cyan'><input type="radio" />            <p>青色</p>            </div>   <div class='checkbox blue'><input type="radio" />            <p>蓝色</p>            </div></div><div class="tab-item-content" id="radio-4"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;% radio 纯文本测试 %&#125;</span><br><span class="line">&#123;% radio checked, 支持简单的 [<span class="string">markdown</span>](<span class="link">https://guides.github.com/features/mastering-markdown/</span>) 语法 %&#125;</span><br><span class="line">&#123;% radio red, 支持自定义颜色 %&#125;</span><br><span class="line">&#123;% radio green, 绿色 %&#125;</span><br><span class="line">&#123;% radio yellow, 黄色 %&#125;</span><br><span class="line">&#123;% radio cyan, 青色 %&#125;</span><br><span class="line">&#123;% radio blue, 蓝色 %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="文本相关"><a href="#文本相关" class="headerlink" title="文本相关"></a>文本相关</h2><h3 id="行内文本样式-text"><a href="#行内文本样式-text" class="headerlink" title="行内文本样式 text"></a>行内文本样式 text</h3><div class="tabs" id="text"><ul class="nav-tabs"><button type="button" class="tab " data-href="text-1">标签语法</button><button type="button" class="tab  active" data-href="text-2">样式预览</button><button type="button" class="tab " data-href="text-3">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="text-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#123;% u 文本内容 %&#125;</span><br><span class="line">&#123;% emp 文本内容 %&#125;</span><br><span class="line">&#123;% wavy 文本内容 %&#125;</span><br><span class="line">&#123;% del 文本内容 %&#125;</span><br><span class="line">&#123;% kbd 文本内容 %&#125;</span><br><span class="line">&#123;% psw 文本内容 %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content active" id="text-2"><ol><li>带 <u>下划线</u> 的文本</li><li>带 <emp>着重号</emp> 的文本</li><li>带 <wavy>波浪线</wavy> 的文本</li><li>带 <del>删除线</del> 的文本</li><li>键盘样式的文本 <kbd>command</kbd> + <kbd>D</kbd></li><li>密码样式的文本：<psw>这里没有验证码</psw></li></ol></div><div class="tab-item-content" id="text-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">1.</span> 带 &#123;% u 下划线 %&#125; 的文本</span><br><span class="line"><span class="bullet">2.</span> 带 &#123;% emp 着重号 %&#125; 的文本</span><br><span class="line"><span class="bullet">3.</span> 带 &#123;% wavy 波浪线 %&#125; 的文本</span><br><span class="line"><span class="bullet">4.</span> 带 &#123;% del 删除线 %&#125; 的文本</span><br><span class="line"><span class="bullet">5.</span> 键盘样式的文本 &#123;% kbd command %&#125; + &#123;% kbd D %&#125;</span><br><span class="line"><span class="bullet">6.</span> 密码样式的文本：&#123;% psw 这里没有验证码 %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="行内文本-span"><a href="#行内文本-span" class="headerlink" title="行内文本 span"></a>行内文本 span</h3><div class="tabs" id="span"><ul class="nav-tabs"><button type="button" class="tab " data-href="span-1">标签语法</button><button type="button" class="tab " data-href="span-2">配置参数</button><button type="button" class="tab  active" data-href="span-3">样式预览</button><button type="button" class="tab " data-href="span-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="span-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% span 样式参数(参数以空格划分), 文本内容 %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="span-2"><ol><li>字体: logo, code</li><li>颜色: <span class='p red'>red</span>,<span class='p yellow'>yellow</span>,<span class='p green'>green</span>,<span class='p cyan'>cyan</span>,<span class='p blue'>blue</span>,<span class='p gray'>gray</span></li><li>大小: small, h4, h3, h2, h1, large, huge, ultra</li><li>对齐方向: left, center, right</li></ol></div><div class="tab-item-content active" id="span-3"><ul><li>彩色文字<br>在一段话中方便插入各种颜色的标签，包括：<span class='p red'>红色</span>、<span class='p yellow'>黄色</span>、<span class='p green'>绿色</span>、<span class='p cyan'>青色</span>、<span class='p blue'>蓝色</span>、<span class='p gray'>灰色</span>。</li><li>超大号文字<br>文档「开始」页面中的标题部分就是超大号文字。<br><span class='p center logo large'>Volantis</span><br><span class='p center small'>A Wonderful Theme for Hexo</span></li></ul></div><div class="tab-item-content" id="span-4"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> 彩色文字</span><br><span class="line">在一段话中方便插入各种颜色的标签，包括：&#123;% span red, 红色 %&#125;、&#123;% span yellow, 黄色 %&#125;、&#123;% span green, 绿色 %&#125;、&#123;% span cyan, 青色 %&#125;、&#123;% span blue, 蓝色 %&#125;、&#123;% span gray, 灰色 %&#125;。</span><br><span class="line"><span class="bullet">-</span> 超大号文字</span><br><span class="line">文档「开始」页面中的标题部分就是超大号文字。</span><br><span class="line">&#123;% span center logo large, Volantis %&#125;</span><br><span class="line">&#123;% span center small, A Wonderful Theme for Hexo %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="段落文本-p"><a href="#段落文本-p" class="headerlink" title="段落文本 p"></a>段落文本 p</h3><div class="tabs" id="p"><ul class="nav-tabs"><button type="button" class="tab " data-href="p-1">标签语法</button><button type="button" class="tab " data-href="p-2">配置参数</button><button type="button" class="tab  active" data-href="p-3">样式预览</button><button type="button" class="tab " data-href="p-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="p-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% p 样式参数(参数以空格划分), 文本内容 %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="p-2"><ol><li>字体: logo, code</li><li>颜色: <span class='p red'>red</span>,<span class='p yellow'>yellow</span>,<span class='p green'>green</span>,<span class='p cyan'>cyan</span>,<span class='p blue'>blue</span>,<span class='p gray'>gray</span></li><li>大小: small, h4, h3, h2, h1, large, huge, ultra</li><li>对齐方向: left, center, right</li></ol></div><div class="tab-item-content active" id="p-3"><ul><li>彩色文字<br>在一段话中方便插入各种颜色的标签，包括：<p class='p red'>红色</p>、<p class='p yellow'>黄色</p>、<p class='p green'>绿色</p>、<p class='p cyan'>青色</p>、<p class='p blue'>蓝色</p>、<p class='p gray'>灰色</p>。</li><li>超大号文字<br>文档「开始」页面中的标题部分就是超大号文字。<p class='p center logo large'>Volantis</p><p class='p center small'>A Wonderful Theme for Hexo</p></li></ul></div><div class="tab-item-content" id="p-4"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> 彩色文字</span><br><span class="line">在一段话中方便插入各种颜色的标签，包括：&#123;% p red, 红色 %&#125;、&#123;% p yellow, 黄色 %&#125;、&#123;% p green, 绿色 %&#125;、&#123;% p cyan, 青色 %&#125;、&#123;% p blue, 蓝色 %&#125;、&#123;% p gray, 灰色 %&#125;。</span><br><span class="line"><span class="bullet">-</span> 超大号文字</span><br><span class="line">文档「开始」页面中的标题部分就是超大号文字。</span><br><span class="line">&#123;% p center logo large, Volantis %&#125;</span><br><span class="line">&#123;% p center small, A Wonderful Theme for Hexo %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="时间轴-timeline"><a href="#时间轴-timeline" class="headerlink" title="时间轴 timeline"></a>时间轴 timeline</h2><div class="tabs" id="timeline"><ul class="nav-tabs"><button type="button" class="tab " data-href="timeline-1">标签语法</button><button type="button" class="tab  active" data-href="timeline-2">样式预览</button><button type="button" class="tab " data-href="timeline-3">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="timeline-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#123;% timeline 时间线标题（可选）[,color] %&#125;</span><br><span class="line">&lt;!-- timeline 时间节点（标题） --&gt;</span><br><span class="line">正文内容</span><br><span class="line">&lt;!-- endtimeline --&gt;</span><br><span class="line">&lt;!-- timeline 时间节点（标题） --&gt;</span><br><span class="line">正文内容</span><br><span class="line">&lt;!-- endtimeline --&gt;</span><br><span class="line">&#123;% endtimeline %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content active" id="timeline-2"><div class="timeline blue"><div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'><p>2020-07</p></div></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>2020-07-24</p></div></div><div class='timeline-item-content'><p>天气不错，适合出去约妹</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>2020-05-15</p></div></div><div class='timeline-item-content'><p>学习 SpringCloud Alibaba</p></div></div></div></div><div class="tab-item-content" id="timeline-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&#123;% timeline 2020-07,blue %&#125;</span><br><span class="line">&lt;!-- timeline 2020-07-24  --&gt;</span><br><span class="line">天气不错，适合出去约妹</span><br><span class="line">&lt;!-- endtimeline --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- timeline 2020-05-15 --&gt;</span><br><span class="line">学习 SpringCloud Alibaba</span><br><span class="line">&lt;!-- endtimeline --&gt;</span><br><span class="line">&#123;% endtimeline %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="链接卡片-link"><a href="#链接卡片-link" class="headerlink" title="链接卡片 link"></a>链接卡片 link</h2><div class="tabs" id="link"><ul class="nav-tabs"><button type="button" class="tab " data-href="link-1">标签语法</button><button type="button" class="tab  active" data-href="link-2">样式预览</button><button type="button" class="tab " data-href="link-3">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="link-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% link 标题, 链接, 图片链接（可选） %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content active" id="link-2"><div class="tag link"><a class="link-card" title="GitHub" href="https://github.com"><div class="left"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.onmicrosoft.cn/gh/cpddo/p_img@450ea647ca67bd386416a689f3eb1bc6a508b3b9/2021/01/23/f7ac7b26db76ada1704f6af09bedacbe.webp"/></div><div class="right"><p class="text">GitHub</p><p class="url">https://github.com</p></div></a></div></div><div class="tab-item-content" id="link-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% link GitHub, https://github.com, https://jsd.onmicrosoft.cn/gh/cpddo/p<span class="emphasis">_img@450ea647ca67bd386416a689f3eb1bc6a508b3b9/2021/01/23/f7ac7b26db76ada1704f6af09bedacbe.webp %&#125;</span></span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="按钮-btns"><a href="#按钮-btns" class="headerlink" title="按钮 btns"></a>按钮 btns</h2><div class="note blue icon-padding simple"><i class="note-icon fas fa-bullhorn"></i><p><code>Volantis</code> 的按钮使用的是 <code>btn</code> 和 <code>btns</code> 标签。<code>btns</code> 和 <code>butterfly</code> 的 <code>button</code> 不冲突，但是 <code>btn</code> 会被强制渲染，导致部分参数失效，而且 <code>btn</code> 的效果还是 <code>butterfly</code> 的 <code>button</code> 更好看些。所以就只适配了 <code>btns</code>。</p></div><div class="tabs" id="btn"><ul class="nav-tabs"><button type="button" class="tab " data-href="btn-1">标签语法</button><button type="button" class="tab " data-href="btn-2">参数配置</button><button type="button" class="tab  active" data-href="btn-3">样式预览</button><button type="button" class="tab " data-href="btn-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="btn-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;% btns 样式参数 %&#125;</span><br><span class="line">&#123;% cell 标题, 链接, 图片或者图标 %&#125;</span><br><span class="line">&#123;% cell 标题, 链接, 图片或者图标 %&#125;</span><br><span class="line">&#123;% endbtns %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="btn-2"><ol><li>圆角样式：rounded, circle</li><li>增加文字样式：可以在容器内增加 <code>&lt;b&gt;标题&lt;/b&gt;</code> 和 <code>&lt;p&gt;描述文字&lt;/p&gt;</code></li><li>布局方式：<br>默认为自动宽度，适合视野内只有一两个的情况。</li></ol><table><thead><tr><th align="left">参数</th><th align="left">含义</th></tr></thead><tbody><tr><td align="left">wide</td><td align="left">宽一点的按钮</td></tr><tr><td align="left">fill</td><td align="left">填充布局，自动铺满至少一行，多了会换行</td></tr><tr><td align="left">center</td><td align="left">居中，按钮之间是固定间距</td></tr><tr><td align="left">around</td><td align="left">居中分散</td></tr><tr><td align="left">grid2</td><td align="left">等宽最多2列，屏幕变窄会适当减少列数</td></tr><tr><td align="left">grid3</td><td align="left">等宽最多3列，屏幕变窄会适当减少列数</td></tr><tr><td align="left">grid4</td><td align="left">等宽最多4列，屏幕变窄会适当减少列数</td></tr><tr><td align="left">grid5</td><td align="left">等宽最多5列，屏幕变窄会适当减少列数</td></tr></tbody></table></div><div class="tab-item-content active" id="btn-3"><ol><li><p>一组含有头像的链接：</p><div class="btns circle grid5">         <a class="button" href='https://github.com/' title='GitHub'><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src='https://jsd.onmicrosoft.cn/gh/cpddo/p_img@450ea647ca67bd386416a689f3eb1bc6a508b3b9/2021/01/23/f7ac7b26db76ada1704f6af09bedacbe.webp'>GitHub</a><a class="button" href='https://www.bilibili.com/' title='哔哩哔哩'><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src='https://jsd.onmicrosoft.cn/gh/cpddo/p_img@e642ee265c8ae2bbd0994716aa12b3adbe07f2c4/2021/01/23/2ceca69a212d3b9988bbd2c41edc636c.webp'>哔哩哔哩</a><a class="button" href='https://www.pixiv.net/' title='Pixiv'><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src='https://jsd.onmicrosoft.cn/gh/cpddo/p_img@5c4fc20944c706aa452c31d1bddbdcc672e8c6ab/2021/01/23/7658d06315d32bcf0c954b3d8e8879e0.webp'>Pixiv</a><a class="button" href='https://www.youtube.com/' title='YouTube'><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src='https://jsd.onmicrosoft.cn/gh/cpddo/p_img@ff4781678ea6227f5824e3c8bfd5cc27441db4da/2021/01/23/f4e292c780275465c9150eb3cb0785a4.webp'>YouTube</a><a class="button" href='https://tophub.today/' title='今日热榜'><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src='https://jsd.onmicrosoft.cn/gh/cpddo/p_img@11fff6ed270722d709eb0ac88ce47f468c21d2ba/2021/01/23/cd22cd9d34d7d7bd58114d7d7a195822.webp'>今日热榜</a>       </div></li><li><p>含有图标的按钮：</p><div class="btns rounded grid5">         <a class="button" href='/' title='下载源码'><i class='fas fa-download'></i>下载源码</a><a class="button" href='/' title='查看文档'><i class='fas fa-book-open'></i>查看文档</a>       </div></li><li><p>圆形图标 + 标题 + 描述 + 图片 + 网格5列 + 居中</p><div class="btns circle center grid5">         <a href='https://apps.apple.com/cn/app/heart-mate-pro-hrm-utility/id1463348922?ls=1'><i class='fab fa-apple'></i><b>心率管家</b><p class='p red'>专业版</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src='https://jsd.onmicrosoft.cn/gh/xaoxuu/cdn-assets/qrcode/heartmate_pro.png'></a><a href='https://apps.apple.com/cn/app/heart-mate-lite-hrm-utility/id1475747930?ls=1'><i class='fab fa-apple'></i><b>心率管家</b><p class='p green'>免费版</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src='https://jsd.onmicrosoft.cn/gh/xaoxuu/cdn-assets/qrcode/heartmate_lite.png'></a>       </div></li></ol></div><div class="tab-item-content" id="btn-4"><ol><li><p>一组含有头像的链接：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;% btns circle grid5 %&#125;</span><br><span class="line">&#123;% cell GitHub, https://github.com/, https://jsd.onmicrosoft.cn/gh/cpddo/p<span class="emphasis">_img@450ea647ca67bd386416a689f3eb1bc6a508b3b9/2021/01/23/f7ac7b26db76ada1704f6af09bedacbe.webp %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% cell 哔哩哔哩, https://www.bilibili.com/, https://jsd.onmicrosoft.cn/gh/cpddo/p_</span>img@e642ee265c8ae2bbd0994716aa12b3adbe07f2c4/2021/01/23/2ceca69a212d3b9988bbd2c41edc636c.webp %&#125;</span><br><span class="line">&#123;% cell Pixiv, https://www.pixiv.net/, https://jsd.onmicrosoft.cn/gh/cpddo/p<span class="emphasis">_img@5c4fc20944c706aa452c31d1bddbdcc672e8c6ab/2021/01/23/7658d06315d32bcf0c954b3d8e8879e0.webp %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% cell YouTube, https://www.youtube.com/, https://jsd.onmicrosoft.cn/gh/cpddo/p_</span>img@ff4781678ea6227f5824e3c8bfd5cc27441db4da/2021/01/23/f4e292c780275465c9150eb3cb0785a4.webp %&#125;</span><br><span class="line">&#123;% cell 今日热榜, https://tophub.today/, https://jsd.onmicrosoft.cn/gh/cpddo/p<span class="emphasis">_img@11fff6ed270722d709eb0ac88ce47f468c21d2ba/2021/01/23/cd22cd9d34d7d7bd58114d7d7a195822.webp %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% endbtns %&#125;</span></span><br></pre></td></tr></table></figure></li><li><p>或者含有图标的按钮：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;% btns rounded grid5 %&#125;</span><br><span class="line">&#123;% cell 下载源码, /, fas fa-download %&#125;</span><br><span class="line">&#123;% cell 查看文档, /, fas fa-book-open %&#125;</span><br><span class="line">&#123;% endbtns %&#125;</span><br></pre></td></tr></table></figure></li><li><p>圆形图标 + 标题 + 描述 + 图片 + 网格5列 + 居中</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&#123;% btns circle center grid5 %&#125;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&#x27;https://apps.apple.com/cn/app/heart-mate-pro-hrm-utility/id1463348922?ls=1&#x27;</span>&gt;</span></span></span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&#x27;fab fa-apple&#x27;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span></span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">b</span>&gt;</span></span>心率管家<span class="language-xml"><span class="tag">&lt;/<span class="name">b</span>&gt;</span></span></span><br><span class="line">  &#123;% p red, 专业版 %&#125;</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&#x27;https://jsd.onmicrosoft.cn/gh/xaoxuu/cdn-assets/qrcode/heartmate_pro.png&#x27;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&#x27;https://apps.apple.com/cn/app/heart-mate-lite-hrm-utility/id1475747930?ls=1&#x27;</span>&gt;</span></span></span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&#x27;fab fa-apple&#x27;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span></span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">b</span>&gt;</span></span>心率管家<span class="language-xml"><span class="tag">&lt;/<span class="name">b</span>&gt;</span></span></span><br><span class="line">  &#123;% p green, 免费版 %&#125;</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&#x27;https://jsd.onmicrosoft.cn/gh/xaoxuu/cdn-assets/qrcode/heartmate_lite.png&#x27;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span></span><br><span class="line">&#123;% endbtns %&#125;</span><br></pre></td></tr></table></figure></li></ol></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="github-卡片-ghcard"><a href="#github-卡片-ghcard" class="headerlink" title="github 卡片 ghcard"></a>github 卡片 ghcard</h2>   <div class="note blue icon-padding modern"><i class="note-icon fas fa-bullhorn"></i><p>ghcard 使用了 <code>github-readme-stats</code> 的 API，支持直接使用 <code>markdown</code> 语法来写。</p></div>   <div class="tabs" id="ghcard"><ul class="nav-tabs"><button type="button" class="tab " data-href="ghcard-1">标签语法</button><button type="button" class="tab " data-href="ghcard-2">配置参数</button><button type="button" class="tab  active" data-href="ghcard-3">样式预览</button><button type="button" class="tab " data-href="ghcard-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="ghcard-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% ghcard 用户名, 其它参数（可选） %&#125;</span><br><span class="line">&#123;% ghcard 用户名/仓库, 其它参数（可选） %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="ghcard-2"><p>更多参数可以参考：<br><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/anuraghazra/github-readme-stats"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=anuraghazra&repo=github-readme-stats&show_owner=true"/></a><br>使用<code>,</code>分割各个参数。写法为：<code>参数名=参数值</code><br>以下只写几个常用参数值。</p><table><thead><tr><th align="left">参数名</th><th align="left">取值</th><th align="left">释义</th></tr></thead><tbody><tr><td align="left">hide</td><td align="left">stars,commits,prs,issues,contribs</td><td align="left">隐藏指定统计</td></tr><tr><td align="left">count_private</td><td align="left">true</td><td align="left">将私人项目贡献添加到总提交计数中</td></tr><tr><td align="left">show_icons</td><td align="left">true</td><td align="left">显示图标</td></tr><tr><td align="left">theme</td><td align="left">请查阅<a href="https://github.com/anuraghazra/github-readme-stats/blob/master/themes/README.md">Available Themes</a></td><td align="left">主题</td></tr></tbody></table></div><div class="tab-item-content active" id="ghcard-3"><ol><li>用户信息卡片</li></ol><table><thead><tr><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/jerryc127"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/?username=jerryc127&show_owner=true"/></a></th><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/Zfour"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/?username=Zfour&theme=vue&show_owner=true"/></a></th></tr></thead><tbody><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/Akilarlxh"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/?username=Akilarlxh&theme=buefy&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/ruanyf"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/?username=ruanyf&theme=solarized-light&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/philwebb"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/?username=philwebb&theme=onedark&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/zjwo"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/?username=zjwo&theme=solarized-dark&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/vpavic"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/?username=vpavic&theme=algolia&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/bclozel"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/?username=bclozel&theme=calm&show_owner=true"/></a></td></tr></tbody></table><ol start="2"><li>仓库信息卡片</li></ol><table><thead><tr><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/spring-projects/spring-boot"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=spring-projects&repo=spring-boot&show_owner=true"/></a></th><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/mybatis/mybatis-3"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=mybatis&repo=mybatis-3&theme=vue&show_owner=true"/></a></th></tr></thead><tbody><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/jerryc127/hexo-theme-butterfly"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=jerryc127&repo=hexo-theme-butterfly&theme=buefy&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/alibaba/fastjson"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=alibaba&repo=fastjson&theme=solarized-light&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/alibaba/druid"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=alibaba&repo=druid&theme=onedark&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/alibaba/arthas"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=alibaba&repo=arthas&theme=solarized-dark&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/Tencent/weui"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=Tencent&repo=weui&theme=algolia&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=calm&show_owner=true"/></a></td></tr></tbody></table></div><div class="tab-item-content" id="ghcard-4"><ol><li><p>用户信息卡片</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">| &#123;% ghcard jerryc127 %&#125;               | &#123;% ghcard Zfour, theme=vue %&#125;              |</span><br><span class="line">| ------------------------------------ | ------------------------------------------ |</span><br><span class="line">| &#123;% ghcard Akilarlxh, theme=buefy %&#125;  | &#123;% ghcard ruanyf, theme=solarized-light %&#125; |</span><br><span class="line">| &#123;% ghcard philwebb, theme=onedark %&#125; | &#123;% ghcard zjwo, theme=solarized-dark %&#125;    |</span><br><span class="line">| &#123;% ghcard vpavic, theme=algolia %&#125;   | &#123;% ghcard bclozel, theme=calm %&#125;           |</span><br></pre></td></tr></table></figure></li><li><p>仓库信息卡片</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">| &#123;% ghcard spring-projects/spring-boot %&#125;                 | &#123;% ghcard mybatis/mybatis-3, theme=vue %&#125;               |</span><br><span class="line">| -------------------------------------------------------- | ------------------------------------------------------- |</span><br><span class="line">| &#123;% ghcard jerryc127/hexo-theme-butterfly, theme=buefy %&#125; | &#123;% ghcard alibaba/fastjson, theme=solarized-light %&#125;    |</span><br><span class="line">| &#123;% ghcard alibaba/druid, theme=onedark %&#125;                | &#123;% ghcard alibaba/arthas, theme=solarized-dark %&#125;       |</span><br><span class="line">| &#123;% ghcard Tencent/weui, theme=algolia %&#125;                 | &#123;% ghcard volantis-x/hexo-theme-volantis, theme=calm %&#125; |</span><br></pre></td></tr></table></figure></li></ol></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="github-徽标-ghbdage"><a href="#github-徽标-ghbdage" class="headerlink" title="github 徽标 ghbdage"></a>github 徽标 ghbdage</h2><div class="tabs" id="ghbdage"><ul class="nav-tabs"><button type="button" class="tab " data-href="ghbdage-1">标签语法</button><button type="button" class="tab " data-href="ghbdage-2">配置参数</button><button type="button" class="tab  active" data-href="ghbdage-3">样式预览</button><button type="button" class="tab " data-href="ghbdage-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="ghbdage-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% bdage [right],[left],[logo]||[color],[link],[title]||[option] %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="ghbdage-2"><ol><li><code>left</code>：徽标左边的信息，必选参数。</li><li><code>right</code>: 徽标右边的信息，必选参数，</li><li><code>logo</code>：徽标图标，图标名称详见<a href="https://simpleicons.org/">simpleicons</a>，可选参数。</li><li><code>color</code>：徽标右边的颜色，可选参数。</li><li><code>link</code>：指向的链接，可选参数。</li><li><code>title</code>：徽标的额外信息，可选参数。主要用于优化SEO，但<code>object</code>标签不会像<code>a</code>标签一样在鼠标悬停显示<code>title</code>信息。</li><li><code>option</code>：自定义参数，支持<a href="https://shields.io/">shields.io</a>的全部API参数支持，具体参数可以参看上文中的拓展写法示例。形式为<code>name1=value2&amp;name2=value2</code>。</li></ol></div><div class="tab-item-content active" id="ghbdage-3"><div class="note info modern"><p>本外挂标签的参数分为三组，用<code>||</code>分割。</p></div><p>基本参数<br><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/Butterfly-Theme-orange?logo=&color=orange&link=&"></object><br><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/Hexo-Frame-orange?logo=hexo&color=orange&link=&"></object></p><p>信息参数<br><object class="ghbdage" style="margin-inline:5px" title="本站使用JsDelivr为静态资源提供CDN加速" standby="loading..." data="https://img.shields.io/badge/JsDelivr-CDN-orange?logo=jsDelivr&color=abcdef&link=https://metroui.org.ua/index.html&"></object><br><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/GitHub-Source-orange?logo=GitHub&color=orange&link=https://github.com/&"></object></p><p>拓展参数<br><object class="ghbdage" style="margin-inline:5px" title="本站采用双线部署，默认线路托管于Vercel" standby="loading..." data="https://img.shields.io/badge/Vercel-Hosted-orange?logo=Vercel&color=brightgreen&link=https://vercel.com/&style=social&logoWidth=40"></object><br><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/Vercel-Hosted-orange?logo=Vercel&color=orange&link=&style=social&logoWidth=40&logoColor=violet"></object></p></div><div class="tab-item-content" id="ghbdage-4"><div class="note info modern"><p>本外挂标签的参数分为三组，用<code>||</code>分割。</p></div><p>基本参数,定义徽标左右文字和图标</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% bdage Theme,Butterfly %&#125;</span><br><span class="line">&#123;% bdage Frame,Hexo,hexo %&#125;</span><br></pre></td></tr></table></figure><p>信息参数，定义徽标右侧内容背景色，指向链接</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% bdage CDN,JsDelivr,jsDelivr||abcdef,https://metroui.org.ua/index.html,本站使用JsDelivr为静态资源提供CDN加速 %&#125;</span><br><span class="line">// 如果是跨顺序省略可选参数，仍然需要写个逗号,用作分割</span><br><span class="line">&#123;% bdage Source,GitHub,GitHub||,https://github.com/ %&#125;</span><br></pre></td></tr></table></figure><p>拓展参数，支持shields的API的全部参数内容</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% bdage Hosted,Vercel,Vercel||brightgreen,https://vercel.com/,本站采用双线部署，默认线路托管于Vercel||style=social&amp;logoWidth=20 %&#125;</span><br><span class="line">// 如果是跨顺序省略可选参数组，仍然需要写双竖线||用作分割</span><br><span class="line">&#123;% bdage Hosted,Vercel,Vercel||||style=social&amp;logoWidth=20&amp;logoColor=violet %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="行内图片-inlineimage"><a href="#行内图片-inlineimage" class="headerlink" title="行内图片 inlineimage"></a>行内图片 inlineimage</h2><p>这是 <img no-lazy class="inline" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-emoji/aru-l/0000.gif" style="height:1.5em"/> 一段话。</p><p>这又是 <img no-lazy class="inline" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-emoji/aru-l/5150.gif" style="height:40px;"/> 一段话。</p><div class="tabs" id="inlineimage"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="inlineimage-1">标签语法</button><button type="button" class="tab " data-href="inlineimage-2">参数配置</button><button type="button" class="tab " data-href="inlineimage-3">示例源码</button><button type="button" class="tab " data-href="inlineimage-4">Butterfly 内置</button></ul><div class="tab-contents"><div class="tab-item-content active" id="inlineimage-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% inlineimage 图片链接, height=高度（可选） %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="inlineimage-2"><ol><li>高度：height=20px</li></ol></div><div class="tab-item-content" id="inlineimage-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">这是 &#123;% inlineimage https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-emoji/aru-l/0000.gif %&#125; 一段话。</span><br><span class="line"></span><br><span class="line">这又是 &#123;% inlineimage https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-emoji/aru-l/5150.gif, height=40px %&#125; 一段话。</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="inlineimage-4"><p>你看我长得漂亮不</p><p>我觉得很漂亮 <img class="inline-img" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-emoji/aru-l/0000.gif" style="height:80px" /></p><p><strong>语法：</strong></p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;% inlineImg [src] [height] %&#125;</span><br><span class="line"></span><br><span class="line">[src]      :    图片链接</span><br><span class="line">[height]   ：   图片高度限制【可选】</span><br></pre></td></tr></table></figure><p><strong>示例源码：</strong></p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">你看我长得漂亮不</span><br><span class="line"></span><br><span class="line">我觉得很漂亮 &#123;% inlineImg https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-emoji/aru-l/0000.gif 80px %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="单张图片-image"><a href="#单张图片-image" class="headerlink" title="单张图片 image"></a>单张图片 image</h2><div class="tabs" id="image"><ul class="nav-tabs"><button type="button" class="tab " data-href="image-1">标签语法</button><button type="button" class="tab " data-href="image-2">参数配置</button><button type="button" class="tab  active" data-href="image-3">样式预览</button><button type="button" class="tab " data-href="image-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="image-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% image 链接, width=宽度（可选）, height=高度（可选）, alt=描述（可选）, bg=占位颜色（可选） %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="image-2"><ol><li><p>图片宽度高度：width=300px, height=32px</p></li><li><p>图片描述：alt=图片描述（butterfly需要在主题配置文件中开启图片描述）</p></li><li><p>占位背景色：bg=#f2f2f2</p></li></ol></div><div class="tab-item-content active" id="image-3"><ol start="4"><li><p>添加描述：</p><div class="img-wrap"><div class="img-bg"><img class="img" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg" alt="每天下课回宿舍的路，没有什么故事。"/></div><span class="image-caption">每天下课回宿舍的路，没有什么故事。</span></div></li><li><p>指定宽度：</p><div class="img-wrap"><div class="img-bg"><img class="img" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg" style="width:400px;"/></div></div></li><li><p>指定宽度并添加描述：</p><div class="img-wrap"><div class="img-bg"><img class="img" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg" alt="每天下课回宿舍的路，没有什么故事。" style="width:400px;"/></div><span class="image-caption">每天下课回宿舍的路，没有什么故事。</span></div></li><li><p>设置占位背景色：</p><div class="img-wrap"><div class="img-bg" style="background:#1D0C04"><img class="img" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg" alt="优化不同宽度浏览的观感" style="width:400px;"/></div><span class="image-caption">优化不同宽度浏览的观感</span></div></li></ol></div><div class="tab-item-content" id="image-4"><ol><li><p>添加描述：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% image https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg, alt=每天下课回宿舍的路，没有什么故事。 %&#125;</span><br></pre></td></tr></table></figure></li><li><p>指定宽度：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% image https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg, width=400px %&#125;</span><br></pre></td></tr></table></figure></li><li><p>指定宽度并添加描述：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% image https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg, width=400px, alt=每天下课回宿舍的路，没有什么故事。 %&#125;</span><br></pre></td></tr></table></figure></li><li><p>设置占位背景色：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% image https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg, width=400px, bg=#1D0C04, alt=优化不同宽度浏览的观感 %&#125;</span><br></pre></td></tr></table></figure></li></ol></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="音频-audio"><a href="#音频-audio" class="headerlink" title="音频 audio"></a>音频 audio</h2><div class="tabs" id="audio"><ul class="nav-tabs"><button type="button" class="tab " data-href="audio-1">标签语法</button><button type="button" class="tab  active" data-href="audio-2">样式预览</button><button type="button" class="tab " data-href="audio-3">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="audio-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% audio 音频链接 %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content active" id="audio-2"><div class="audio"><audio controls preload><source src='https://music.163.com/song/media/outer/url?id=1360515273.mp3' type='audio/mp3'>Your browser does not support the audio tag.</audio></div><div class="audio"><audio controls preload><source src='https://music.163.com/song/media/outer/url?id=316501.mp3' type='audio/mp3'>Your browser does not support the audio tag.</audio></div></div><div class="tab-item-content" id="audio-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% audio https://音乐链接.mp3 %&#125;</span><br><span class="line">&#123;% audio https://音乐链接.mp3 %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="视频-video"><a href="#视频-video" class="headerlink" title="视频 video"></a>视频 video</h2><div class="tabs" id="video"><ul class="nav-tabs"><button type="button" class="tab " data-href="video-1">标签语法</button><button type="button" class="tab " data-href="video-2">参数配置</button><button type="button" class="tab  active" data-href="video-3">样式预览</button><button type="button" class="tab " data-href="video-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="video-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% video 视频链接 %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="video-2"><ol><li>对其方向：left, center, right</li><li>列数：逗号后面直接写列数，支持 1 ～ 4 列。</li></ol></div><div class="tab-item-content active" id="video-3"><ol><li><p>100% 宽度</p><div class="video"><video controls preload><source src='https://media.w3.org/2010/05/sintel/trailer.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div></li><li><p>50% 宽度</p><div class="videos" col='2'><div class="video"><video controls preload><source src='https://media.w3.org/2010/05/sintel/trailer.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://bos.nj.bpc.baidu.com/tieba-smallvideo-transcode-crf/10517287_a019c0a4655b865403740b7b9d1f0622_0.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div></div></li><li><p>25% 宽度</p><div class="videos" col='4'><div class="video"><video controls preload><source src='https://www.w3school.com.cn/example/html5/mov_bbb.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://www.w3school.com.cn/example/html5/mov_bbb.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://www.w3school.com.cn/example/html5/mov_bbb.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://www.w3school.com.cn/example/html5/mov_bbb.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://www.w3school.com.cn/example/html5/mov_bbb.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://www.w3school.com.cn/example/html5/mov_bbb.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://www.w3school.com.cn/example/html5/mov_bbb.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://www.w3school.com.cn/example/html5/mov_bbb.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div></div></li></ol></div><div class="tab-item-content" id="video-4"><ol><li><p>100% 宽度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% video 视频链接 %&#125;</span><br></pre></td></tr></table></figure></li><li><p>50% 宽度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#123;% videos, 2 %&#125;</span><br><span class="line">&#123;% video 视频链接 %&#125;</span><br><span class="line">&#123;% video 视频链接 %&#125;</span><br><span class="line">&#123;% video 视频链接 %&#125;</span><br><span class="line">&#123;% video 视频链接 %&#125;</span><br><span class="line">&#123;% endvideos %&#125;</span><br></pre></td></tr></table></figure></li><li><p>25% 宽度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&#123;% videos, 4 %&#125;</span><br><span class="line">&#123;% video https://www.w3school.com.cn/example/html5/mov<span class="emphasis">_bbb.mp4 %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% video https://www.w3school.com.cn/example/html5/mov_</span>bbb.mp4 %&#125;</span><br><span class="line">&#123;% video https://www.w3school.com.cn/example/html5/mov<span class="emphasis">_bbb.mp4 %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% video https://www.w3school.com.cn/example/html5/mov_</span>bbb.mp4 %&#125;</span><br><span class="line">&#123;% video https://www.w3school.com.cn/example/html5/mov<span class="emphasis">_bbb.mp4 %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% video https://www.w3school.com.cn/example/html5/mov_</span>bbb.mp4 %&#125;</span><br><span class="line">&#123;% video https://www.w3school.com.cn/example/html5/mov<span class="emphasis">_bbb.mp4 %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% video https://www.w3school.com.cn/example/html5/mov_</span>bbb.mp4 %&#125;</span><br><span class="line">&#123;% endvideos %&#125;</span><br></pre></td></tr></table></figure></li></ol></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="相册-gallery"><a href="#相册-gallery" class="headerlink" title="相册 gallery"></a>相册 gallery</h2><div class="note success flat"><p>以下为 <code>Butterfly</code> 自带的 <code>gallery</code> 标签写法。相册图库和相册配合使用。</p></div><div class="tabs" id="gallery"><ul class="nav-tabs"><button type="button" class="tab " data-href="gallery-1">标签语法</button><button type="button" class="tab " data-href="gallery-2">参数配置</button><button type="button" class="tab  active" data-href="gallery-3">样式预览</button><button type="button" class="tab " data-href="gallery-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="gallery-1"><ol><li><p>gallerygroup 相册图库</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;gallery-group-main&quot;</span>&gt;</span></span></span><br><span class="line">&#123;% galleryGroup name description link img-url %&#125;</span><br><span class="line">&#123;% galleryGroup name description link img-url %&#125;</span><br><span class="line">&#123;% galleryGroup name description link img-url %&#125;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br></pre></td></tr></table></figure></li><li><p>gallery 相册</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% gallery %&#125;</span><br><span class="line">markdown 图片格式</span><br><span class="line">&#123;% endgallery %&#125;</span><br></pre></td></tr></table></figure></li></ol></div><div class="tab-item-content" id="gallery-2"><ul><li>gallerygroup 相册图库</li></ul><table><thead><tr><th align="left">参数名</th><th align="left">释义</th></tr></thead><tbody><tr><td align="left">name</td><td align="left">图库名字</td></tr><tr><td align="left">description</td><td align="left">图库描述</td></tr><tr><td align="left">link</td><td align="left">链接到对应相册的地址</td></tr><tr><td align="left">img-url</td><td align="left">图库封面</td></tr></tbody></table><div class="note info flat"><p>思维拓展一下，相册图库的实质其实就是个快捷方式，可以自定义添加描述、封面、链接。那么我们未必要把它当做一个相册，完全可以作为一个链接卡片，链接到视频、QQ、友链都是不错的选择。</p></div><ul><li>gallery 相册<br>区别于旧版的 Gallery 相册，新的 Gallery 相册会自动根据图片长度进行排版，书写也更加方便，与 markdown 格式一样。可根据需要插入到相应的 md。无需再自己配置长宽。<strong>建议在粘贴时故意使用长短、大小、横竖不一的图片</strong>，会有更好的效果。（尺寸完全相同的图片只会平铺输出，效果很糟糕）</li></ul></div><div class="tab-item-content active" id="gallery-3"><ul><li>gallerygroup 相册图库</li></ul><div class="gallery-group-main"><figure class="gallery-group">  <img class="gallery-group-img no-lightbox" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src='https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-wallpaper/abstract/41F215B9-261F-48B4-80B5-4E86E165259E.jpeg' alt="Group Image Gallery">  <figcaption>  <div class="gallery-group-name">壁纸</div>  <p>源于网络，侵删！</p>  <a href='/photos/wallpaper/'></a>  </figcaption>  </figure>  </div><ul><li>gallery 相册</li></ul><div class="gallery-container" data-type="data" data-button="">      <div class="gallery-data">[{"url":"https://npm.elemecdn.com/cover_img/wallpaper/work/10.jpg","alt":"images"},{"url":"https://npm.elemecdn.com/cover_img/wallpaper/work/9.jpg","alt":"images"},{"url":"https://npm.elemecdn.com/cover_img/wallpaper/work/8.jpg","alt":"images"},{"url":"https://npm.elemecdn.com/cover_img/wallpaper/work/7.jpg","alt":"images"},{"url":"https://npm.elemecdn.com/cover_img/wallpaper/work/6.jpg","alt":"images"}]</div>      <div class="gallery-items">      </div>    </div></div><div class="tab-item-content" id="gallery-4"><ol><li><p>gallerygroup 相册图库</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;gallery-group-main&quot;</span>&gt;</span></span></span><br><span class="line">&#123;% galleryGroup &#x27;壁纸&#x27; &#x27;源于网络，侵删！&#x27; &#x27;/photos/wallpaper/&#x27; https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-wallpaper/abstract/41F215B9-261F-48B4-80B5-4E86E165259E.jpeg %&#125;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br></pre></td></tr></table></figure></li><li><p>gallery 相册</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;% gallery %&#125;</span><br><span class="line">![<span class="string">images</span>](<span class="link">https://npm.elemecdn.com/cover_img/wallpaper/work/10.jpg</span>)</span><br><span class="line">![<span class="string">images</span>](<span class="link">https://npm.elemecdn.com/cover_img/wallpaper/work/9.jpg</span>)</span><br><span class="line">![<span class="string">images</span>](<span class="link">https://npm.elemecdn.com/cover_img/wallpaper/work/8.jpg</span>)</span><br><span class="line">![<span class="string">images</span>](<span class="link">https://npm.elemecdn.com/cover_img/wallpaper/work/7.jpg</span>)</span><br><span class="line">![<span class="string">images</span>](<span class="link">https://npm.elemecdn.com/cover_img/wallpaper/work/6.jpg</span>)</span><br><span class="line">&#123;% endgallery %&#125;</span><br></pre></td></tr></table></figure></li></ol></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="折叠框-folding"><a href="#折叠框-folding" class="headerlink" title="折叠框 folding"></a>折叠框 folding</h2><div class="tabs" id="folding"><ul class="nav-tabs"><button type="button" class="tab " data-href="folding-1">标签语法</button><button type="button" class="tab " data-href="folding-2">配置参数</button><button type="button" class="tab  active" data-href="folding-3">样式预览</button><button type="button" class="tab " data-href="folding-4">示例源码</button><button type="button" class="tab " data-href="folding-5">Butterfly 内置</button></ul><div class="tab-contents"><div class="tab-item-content" id="folding-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% folding 参数（可选）, 标题 %&#125;</span><br><span class="line">哈哈哈哈</span><br><span class="line">&#123;% endfolding %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="folding-2"><ol><li>颜色：blue, cyan, green, yellow, red</li><li>状态：状态填写 open 代表默认打开。</li></ol></div><div class="tab-item-content active" id="folding-3"><details class="folding-tag" ><summary> 查看图片测试 </summary>              <div class='content'>              <p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-wallpaper/abstract/41F215B9-261F-48B4-80B5-4E86E165259E.jpeg" alt="images"></p>              </div>            </details><details class="folding-tag" cyan open><summary> 查看默认打开的折叠框 </summary>              <div class='content'>              <p>这是一个默认打开的折叠框。</p>              </div>            </details><details class="folding-tag" green><summary> 查看代码测试 </summary>              <div class='content'>              <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>              </div>            </details><details class="folding-tag" yellow><summary> 查看列表测试 </summary>              <div class='content'>              <ul><li>haha</li><li>hehe</li></ul>              </div>            </details><details class="folding-tag" red><summary> 查看嵌套测试 </summary>              <div class='content'>              <details class="folding-tag" blue><summary> 查看嵌套测试2 </summary>              <div class='content'>              <details class="folding-tag" ><summary> 查看嵌套测试3 </summary>              <div class='content'>              <p>hahaha😜</p>              </div>            </details>              </div>            </details>              </div>            </details></div><div class="tab-item-content" id="folding-4"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">&#123;% folding 查看图片测试 %&#125;</span><br><span class="line">![<span class="string">images</span>](<span class="link">https://jsd.onmicrosoft.cn/gh/volantis-x/cdn-wallpaper/abstract/41F215B9-261F-48B4-80B5-4E86E165259E.jpeg</span>)</span><br><span class="line">&#123;% endfolding %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% folding cyan open, 查看默认打开的折叠框 %&#125;</span><br><span class="line">这是一个默认打开的折叠框。</span><br><span class="line">&#123;% endfolding %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% folding green, 查看代码测试 %&#125;</span><br><span class="line">​<span class="code">```java</span></span><br><span class="line"><span class="code">public class Test &#123;</span></span><br><span class="line"><span class="code"></span></span><br><span class="line"><span class="code">&#125;</span></span><br><span class="line"><span class="code">​```</span></span><br><span class="line">&#123;% endfolding %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% folding yellow, 查看列表测试 %&#125;</span><br><span class="line"><span class="bullet">-</span> haha</span><br><span class="line"><span class="bullet">-</span> hehe</span><br><span class="line">&#123;% endfolding %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% folding red, 查看嵌套测试 %&#125;</span><br><span class="line">&#123;% folding blue, 查看嵌套测试2 %&#125;</span><br><span class="line">&#123;% folding 查看嵌套测试3 %&#125;</span><br><span class="line">hahaha😜</span><br><span class="line">&#123;% endfolding %&#125;</span><br><span class="line">&#123;% endfolding %&#125;</span><br><span class="line">&#123;% endfolding %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="folding-5"><p><strong>语法：</strong></p><p>( display 不能包含英文逗号，可用 <code>&amp;sbquo;</code> )</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% hideToggle display,bg,color %&#125;</span><br><span class="line">content</span><br><span class="line">&#123;% endhideToggle %&#125;</span><br></pre></td></tr></table></figure><details class="toggle" ><summary class="toggle-button" style="">Butterfly 安装方法</summary><div class="toggle-content"><p>在你的博客根目录里</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/Butterfly</span><br></pre></td></tr></table></figure><p>如果想要安装比较新的 dev 分支，可以</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> -b dev https://github.com/jerryc127/hexo-theme-butterfly.git themes/Butterfly&#123;% endhideToggle %&#125;</span><br></pre></td></tr></table></figure></div></details><p><strong>示例源码：</strong></p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&#123;% hideToggle Butterfly 安装方法 %&#125;</span><br><span class="line">在你的博客根目录里</span><br><span class="line"></span><br><span class="line">​<span class="code">```sh</span></span><br><span class="line"><span class="code">git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/Butterfly</span></span><br><span class="line"><span class="code">​```</span></span><br><span class="line"></span><br><span class="line">如果想要安装比较新的 dev 分支，可以</span><br><span class="line"></span><br><span class="line">​<span class="code">```sh</span></span><br><span class="line"><span class="code">git clone -b dev https://github.com/jerryc127/hexo-theme-butterfly.git themes/Butterfly&#123;% endhideToggle %&#125;</span></span><br><span class="line"><span class="code">​```</span></span><br><span class="line"></span><br><span class="line">&#123;% endhideToggle %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="分栏-tab"><a href="#分栏-tab" class="headerlink" title="分栏 tab"></a>分栏 tab</h2><div class="tabs" id="folding"><ul class="nav-tabs"><button type="button" class="tab " data-href="folding-1">标签语法</button><button type="button" class="tab " data-href="folding-2">配置参数</button><button type="button" class="tab  active" data-href="folding-3">样式预览</button><button type="button" class="tab " data-href="folding-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="folding-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tabs Unique name, [index] %&#125;</span><br><span class="line">&lt;!-- tab [Tab caption] [@icon] --&gt;</span><br><span class="line">Any content (support inline tags too).</span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line">&#123;% endtabs %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="folding-2"><ol><li>Unique name :<ul><li>选项卡块标签的唯一名称，不带逗号。</li><li>将在#id中用作每个标签及其索引号的前缀。</li><li>如果名称中包含空格，则对于生成#id，所有空格将由破折号代替。</li><li>仅当前帖子/页面的URL必须是唯一的！</li></ul></li><li>[index]:<ul><li>活动选项卡的索引号。</li><li>如果未指定，将选择第一个标签（1）。</li><li>如果index为-1，则不会选择任何选项卡。</li><li>可选参数。</li></ul></li><li>[Tab caption]:<ul><li>当前选项卡的标题。</li><li>如果未指定标题，则带有制表符索引后缀的唯一名称将用作制表符的标题。</li><li>如果未指定标题，但指定了图标，则标题将为空。</li><li>可选参数。</li></ul></li><li>[@icon]:<ul><li>FontAwesome图标名称（全名，看起来像“ fas fa-font”）</li><li>可以指定带空格或不带空格；</li><li>例如’Tab caption @icon’ 和 ‘Tab caption@icon’.</li><li>可选参数。</li></ul></li></ol></div><div class="tab-item-content active" id="folding-3"><div class="note primary flat"><p>Demo 1 - 预设选择第一个【默认】</p></div><div class="tabs" id="test1"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="test1-1">test1 1</button><button type="button" class="tab " data-href="test1-2">test1 2</button><button type="button" class="tab " data-href="test1-3">test1 3</button></ul><div class="tab-contents"><div class="tab-item-content active" id="test1-1"><p><strong>This is Tab 1.</strong></p></div><div class="tab-item-content" id="test1-2"><p><strong>This is Tab 2.</strong></p></div><div class="tab-item-content" id="test1-3"><p><strong>This is Tab 3.</strong></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><div class="note primary flat"><p>Demo 2 - 预设选择tabs</p></div><div class="tabs" id="test2"><ul class="nav-tabs"><button type="button" class="tab " data-href="test2-1">test2 1</button><button type="button" class="tab " data-href="test2-2">test2 2</button><button type="button" class="tab  active" data-href="test2-3">test2 3</button></ul><div class="tab-contents"><div class="tab-item-content" id="test2-1"><p><strong>This is Tab 1.</strong></p></div><div class="tab-item-content" id="test2-2"><p><strong>This is Tab 2.</strong></p></div><div class="tab-item-content active" id="test2-3"><p><strong>This is Tab 3.</strong></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><div class="note primary flat"><p>Demo 3 - 没有预设值</p></div><div class="tabs" id="test3"><ul class="nav-tabs no-default"><button type="button" class="tab " data-href="test3-1">test3 1</button><button type="button" class="tab " data-href="test3-2">test3 2</button><button type="button" class="tab " data-href="test3-3">test3 3</button></ul><div class="tab-contents"><div class="tab-item-content" id="test3-1"><p><strong>This is Tab 1.</strong></p></div><div class="tab-item-content" id="test3-2"><p><strong>This is Tab 2.</strong></p></div><div class="tab-item-content" id="test3-3"><p><strong>This is Tab 3.</strong></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><div class="note primary flat"><p>Demo 4 - 自定义 Tab 名 + 只有 icon + icon 和 Tab 名</p></div><div class="tabs" id="test4"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="test4-1">第一个Tab</button><button type="button" class="tab " data-href="test4-2"><i class="fab fa-apple-pay" style="text-align: center;"></i></button><button type="button" class="tab " data-href="test4-3"><i class="fas fa-bomb"></i>炸弹</button></ul><div class="tab-contents"><div class="tab-item-content active" id="test4-1"><p><strong>tab名字为第一个Tab</strong></p></div><div class="tab-item-content" id="test4-2"><p><strong>只有图标 没有Tab名字</strong></p></div><div class="tab-item-content" id="test4-3"><p><strong>名字+icon</strong></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><div class="tab-item-content" id="folding-4"><div class="note primary flat"><p>Demo 1 - 预设选择第一个【默认】</p></div><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tabs test1 %&#125;</span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 1.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 2.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 3.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line">&#123;% endtabs %&#125;</span><br></pre></td></tr></table></figure><div class="note primary flat"><p>Demo 2 - 预设选择tabs</p></div><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tabs test2, 3 %&#125;</span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 1.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 2.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 3.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line">&#123;% endtabs %&#125;</span><br></pre></td></tr></table></figure><div class="note primary flat"><p>Demo 3 - 没有预设值</p></div><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tabs test3, -1 %&#125;</span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 1.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 2.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 3.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line">&#123;% endtabs %&#125;</span><br></pre></td></tr></table></figure><div class="note primary flat"><p>Demo 4 - 自定义 Tab 名 + 只有 icon + icon 和 Tab 名</p></div><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tabs test4 %&#125;</span><br><span class="line">&lt;!-- tab 第一个Tab --&gt;</span><br><span class="line"><span class="strong">**tab名字为第一个Tab**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab @fab fa-apple-pay --&gt;</span><br><span class="line"><span class="strong">**只有图标 没有Tab名字**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab 炸弹@fas fa-bomb --&gt;</span><br><span class="line"><span class="strong">**名字+icon**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line">&#123;% endtabs %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="诗词标签-poem"><a href="#诗词标签-poem" class="headerlink" title="诗词标签 poem"></a>诗词标签 poem</h2><div class="tabs" id="poem"><ul class="nav-tabs"><button type="button" class="tab " data-href="poem-1">标签语法</button><button type="button" class="tab " data-href="poem-2">参数配置</button><button type="button" class="tab  active" data-href="poem-3">样式预览</button><button type="button" class="tab " data-href="poem-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="poem-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% poem [title],[author] %&#125;</span><br><span class="line">诗词内容</span><br><span class="line">&#123;% endpoem %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="poem-2"><ol><li>title：诗词标题</li><li>author：作者，可以不写</li></ol></div><div class="tab-item-content active" id="poem-3"><div class='poem'><div class='poem-title'>水调歌头</div><div class='poem-author'>苏轼</div><p>明月几时有？把酒问青天。<br>不知天上宫阙，今夕是何年？<br>我欲乘风归去，又恐琼楼玉宇，高处不胜寒。<br>起舞弄清影，何似在人间？<br>转朱阁，低绮户，照无眠。<br>不应有恨，何事长向别时圆？<br>人有悲欢离合，月有阴晴圆缺，此事古难全。<br>但愿人长久，千里共婵娟。</p></div></div><div class="tab-item-content" id="poem-4"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&#123;% poem 水调歌头,苏轼 %&#125;</span><br><span class="line">丙辰中秋，欢饮达旦，大醉，作此篇，兼怀子由。</span><br><span class="line">明月几时有？把酒问青天。</span><br><span class="line">不知天上宫阙，今夕是何年？</span><br><span class="line">我欲乘风归去，又恐琼楼玉宇，高处不胜寒。</span><br><span class="line">起舞弄清影，何似在人间？</span><br><span class="line"></span><br><span class="line">转朱阁，低绮户，照无眠。</span><br><span class="line">不应有恨，何事长向别时圆？</span><br><span class="line">人有悲欢离合，月有阴晴圆缺，此事古难全。</span><br><span class="line">但愿人长久，千里共婵娟。</span><br><span class="line">&#123;% endpoem %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="label"><a href="#label" class="headerlink" title="label"></a>label</h2><p>适用于 Butterfly 3.7.5 及以上版本</p><div class="tabs" id="label"><ul class="nav-tabs"><button type="button" class="tab " data-href="label-1">标签语法</button><button type="button" class="tab " data-href="label-2">参数配置</button><button type="button" class="tab  active" data-href="label-3">样式预览</button><button type="button" class="tab " data-href="label-4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="label-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% label text color %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="label-2"><table><thead><tr><th align="center">参数</th><th align="center">解释</th></tr></thead><tbody><tr><td align="center">text</td><td align="center">文字</td></tr><tr><td align="center">color</td><td align="center">【可选】背景颜色，默认为 <code>default</code> <br/>default / blue / pink / red / purple / orange / green</td></tr></tbody></table></div><div class="tab-item-content active" id="label-3"><p>臣亮言：<mark class="hl-label default">先帝</mark> 创业未半，而<mark class="hl-label blue">中道崩殂</mark> 。今天下三分，<mark class="hl-label pink">益州疲敝</mark> ，此诚<mark class="hl-label red">危急存亡之秋</mark> 也！然侍衞之臣，不懈于内；<mark class="hl-label purple">忠志之士</mark> ，忘身于外者，盖追先帝之殊遇，欲报之于陛下也。诚宜开张圣听，以光先帝遗德，恢弘志士之气；不宜妄自菲薄，引喻失义，以塞忠谏之路也。<br>宫中、府中，俱为一体；陟罚臧否，不宜异同。若有<mark class="hl-label orange">作奸</mark> 、<mark class="hl-label green">犯科</mark> ，及为忠善者，宜付有司，论其刑赏，以昭陛下平明之治；不宜偏私，使内外异法也。</p></div><div class="tab-item-content" id="label-4"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">臣亮言：&#123;% label 先帝 %&#125;创业未半，而&#123;% label 中道崩殂 blue %&#125;。今天下三分，&#123;% label 益州疲敝 pink %&#125;，此诚&#123;% label 危急存亡之秋 red %&#125;也！然侍衞之臣，不懈于内；&#123;% label 忠志之士 purple %&#125;，忘身于外者，盖追先帝之殊遇，欲报之于陛下也。诚宜开张圣听，以光先帝遗德，恢弘志士之气；不宜妄自菲薄，引喻失义，以塞忠谏之路也。</span><br><span class="line">宫中、府中，俱为一体；陟罚臧否，不宜异同。若有&#123;% label 作奸 orange %&#125;、&#123;% label 犯科 green %&#125;，及为忠善者，宜付有司，论其刑赏，以昭陛下平明之治；不宜偏私，使内外异法也。</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="进度条-progress"><a href="#进度条-progress" class="headerlink" title="进度条 progress"></a>进度条 progress</h2><div class="tabs" id="progress-"><ul class="nav-tabs"><button type="button" class="tab " data-href="progress--1">标签语法</button><button type="button" class="tab " data-href="progress--2">参数配置</button><button type="button" class="tab  active" data-href="progress--3">样式预览</button><button type="button" class="tab " data-href="progress--4">示例源码</button></ul><div class="tab-contents"><div class="tab-item-content" id="progress--1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% progress [width] [color] [text] %&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="progress--2"><p>width：0 到 100 的阿拉伯数字<br>color：颜色，取值有 <span class='p red'>red</span>、<span class='p yellow'>yellow</span>、<span class='p green'>green</span>、<span class='p cyan'>cyan</span>、<span class='p blue'>blue</span>、<span class='p gray'>gray</span><br>text：进度条上的文字内容</p></div><div class="tab-item-content active" id="progress--3"><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-red"  style="width: 10%" aria-valuenow="10" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-yellow"  style="width: 30%" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-green"  style="width: 50%" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-cyan"  style="width: 70%" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-blue"  style="width: 90%" aria-valuenow="90" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-gray"  style="width: 100%" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div></div><div class="tab-item-content" id="progress--4"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#123;% progress 10 red 进度条样式预览 %&#125;</span><br><span class="line">&#123;% progress 30 yellow 进度条样式预览 %&#125;</span><br><span class="line">&#123;% progress 50 green 进度条样式预览 %&#125;</span><br><span class="line">&#123;% progress 70 cyan 进度条样式预览 %&#125;</span><br><span class="line">&#123;% progress 90 blue 进度条样式预览 %&#125;</span><br><span class="line">&#123;% progress 100 gray 进度条样式预览 %&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div>]]></content>
    
    
    <summary type="html">原生 Butterfly 主题不支持部分标签外挂，若想使用参考 Tag Plugins Plus，Front-matter，Front-matter 是文件最上方以 --- 分隔的区域，写法，写法解释，title【必需】页面标题，date【必需】页面创建日期，type【必需】标籤、分类和友情链接三个页面需要配置</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="Butterfly" scheme="https://blog.imzjw.cn/tags/Butterfly/"/>
    
  </entry>
  
  <entry>
    <title>记一次申请 SSL 证书被 Vercel 所埋下的坑</title>
    <link href="https://blog.imzjw.cn/posts/c8bfd1b4/"/>
    <id>https://blog.imzjw.cn/posts/c8bfd1b4/</id>
    <published>2021-04-26T07:46:24.000Z</published>
    <updated>2021-04-26T07:46:24.000Z</updated>
    
    <content type="html"><![CDATA[<p>自上个月开始就一直反反复复的申请 SSL，无数次的提交审核、审核失败，最后在腾讯云提交工单之后，可曾想却是 Vercel 的问题。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c8bfd1b4/ggg.wewv2d1na9s.webp" alt="images"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c8bfd1b4/gww.1bk3w17emb1c.webp" alt="images"></p><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>最开始，我是没有提交工单的，找的在线人工的，但说实话，我感觉那个腾讯人工很水，他叫我域名验证的时候选择手动验证…..我心想，这和我自动验证最后审核失败有什么关系嘛…</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c8bfd1b4/talk.3mofg5vdgu40.webp" alt="images"></p><p>这里我要说下，这个手动验证和自动验证就是 手动的你得自己添加记录值，自动的则是由腾讯云自动的帮你添加解析记录，无需自个手动添加。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c8bfd1b4/bwe.4juw96iu6z20.webp" alt="images"></p><p>我还天真的回了句 “我去试试”</p><p>最后通过 <a href="https://myssl.com/dns_check.html#ssl_verify">MySSL</a> 的 SSL 验证工具箱，得知问题</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c8bfd1b4/gq42.5ekg6yfylx00.webp" alt="images"></p><p>问了人工，可人工却…</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c8bfd1b4/eere.5z3iqqeuyog0.webp" alt="images"></p><p>乌鱼子</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c8bfd1b4/ass.6sluk069qec0.webp" alt="images"></p><p>哦对，我还得吐槽一下，™的找人工简直就是浪费时间，10：30 到 12：38 浪费我两个小时，中途还等了 1 个小时</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c8bfd1b4/u33.3kfe5o2e7s60.webp" alt="images"></p><p>你说解决了还好，可最后也没解决，还要我点击【已解决】…这真的很过分了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c8bfd1b4/s66.1a895w10zjhc.webp" alt="images"></p><p>最后还是提交了工单，工单回复的速度也慢的一批，第二天才告知我…</p><h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>通过提交工单之后发现这个问题是 Vercel 的 CNAME 值有问题，因为 Vercel 的 CNAME 值有 CAA 记录，就是因为这个 CAA 记录限制了证书颁发机构从而导致审核失败。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c8bfd1b4/nbbw.7jv8me2f0v40.webp" alt="images"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c8bfd1b4/g44.36q6qfqk33i0.webp" alt="images"></p><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><p>在申请 SSL 证书的时候，暂停解析再去申请。</p><p>结果很快啊，一分钟都没有就颁发下来了。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/c8bfd1b4/23sss.25wnxdhxms3k.webp" alt="images"></p><p>真的是气 “死” 我了！</p>]]></content>
    
    
    <summary type="html">自上个月开始就一直反反复复的申请 SSL，无数次的提交审核、审核失败，最后在腾讯云提交工单之后，可曾想却是 Vercel 的问题。最开始，我是没有提交工单的，找的在线人工的，但说实话，我感觉那个腾讯人工很水</summary>
    
    
    
    <category term="经验分享" scheme="https://blog.imzjw.cn/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="Vercel" scheme="https://blog.imzjw.cn/tags/Vercel/"/>
    
    <category term="SSL" scheme="https://blog.imzjw.cn/tags/SSL/"/>
    
  </entry>
  
  <entry>
    <title>Json 如何快速转 Java 类</title>
    <link href="https://blog.imzjw.cn/posts/7a4477da/"/>
    <id>https://blog.imzjw.cn/posts/7a4477da/</id>
    <published>2021-04-25T09:05:11.000Z</published>
    <updated>2021-04-25T09:05:11.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>一般后端程序员经常会有封装一些调用第三方接口的需求，这些第三方接口的参数和返回值都是提供方定义好的了，我们封装时需要自己手动来生成 <code>POJO</code> 类，像这种一点技术含量都没有的东西，谁都不想手动生成。好在，我们可以利用 IDEA 插件帮助我们生成。</p><h2 id="RoboPOJOGenerator"><a href="#RoboPOJOGenerator" class="headerlink" title="RoboPOJOGenerator"></a>RoboPOJOGenerator</h2><p>一款 Json 转 Java 类的 IDEA 插件，支持将 Json 转成 Java 或者 Kotlin 两种语言，而且还支持 GSON，FastJSON，Jackson，AutoValue (GSON)，Logan Square 这些 Json 框架</p><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>直接插件市场搜 <code>RoboPOJOGenerator</code> 安装就好了</p><h2 id="如何使用"><a href="#如何使用" class="headerlink" title="如何使用"></a>如何使用</h2><p>在此之前，我在本机搜了下 JSON 文件，发现基本都是 <code>package.json</code>，索性就用 Butterfly 主题下的 <code>package.json</code> 来演示一下</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;hexo-theme-butterfly&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;version&quot;</span><span class="punctuation">:</span> <span class="string">&quot;3.7.5-b4&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;description&quot;</span><span class="punctuation">:</span> <span class="string">&quot;A Simple and Card UI Design theme for Hexo&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;main&quot;</span><span class="punctuation">:</span> <span class="string">&quot;package.json&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;scripts&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;test&quot;</span><span class="punctuation">:</span> <span class="string">&quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;keywords&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="string">&quot;hexo&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;theme&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;butterfly&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;Card UI Design&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;Jerry&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;hexo-theme-butterfly&quot;</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;repository&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;type&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;git&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;url&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;https://github.com/jerryc127/hexo-theme-butterfly.git&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;bugs&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;url&quot;</span><span class="punctuation">:</span> <span class="string">&quot;https://github.com/jerryc127/hexo-theme-butterfly/issues&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;email&quot;</span><span class="punctuation">:</span> <span class="string">&quot;btf@immyw.com&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;dependencies&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;hexo-renderer-stylus&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^2.0.1&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;hexo-renderer-pug&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^1.0.0&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;homepage&quot;</span><span class="punctuation">:</span> <span class="string">&quot;https://butterfly.js.org/&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;author&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Jerry &lt;btf@immyw.com&gt;&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;license&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Apache-2.0&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>在 IDEA 中，右键 <code>new</code> –&gt; <code>Generate POJO from JSON</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7a4477da/xxx.a8db8ns9gmg.webp" alt="images"></p><p>把演示的 JSON 粘贴进去，最后点击生成。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7a4477da/json.22vke7q8ckzk.webp" alt="json"></p><p>多快速</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7a4477da/lei.571rsuqvsqs0.webp" alt="images"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7a4477da/kkk.6ap0adh1qps0.webp" alt="images"></p><p>还有另一款 <code>GsonFormatPlus</code></p><h2 id="GsonFormatPlus"><a href="#GsonFormatPlus" class="headerlink" title="GsonFormatPlus"></a>GsonFormatPlus</h2><p>一个根据 <code>JSONObject</code> 格式的字符串，自动生成实体类参数，基于 GsonFormat 二次定制化开发的 idea json 生成 Bean 插件，支持 Lombok 和属性类型修改。</p><p>首先要先创建一个类，然后快捷键 <kbd>ALT</kbd> + <kbd>S</kbd>，把 JSON 粘贴进去</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7a4477da/gggg.714recgg2o40.webp" alt="images"></p><p>点击 OK 完成生成！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7a4477da/bbbbb.2steda95squ0.webp" alt="images"></p><p>生成的 JAVA 类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Butterfly</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> String link;</span><br><span class="line">    <span class="keyword">private</span> String descr;</span><br><span class="line">    <span class="keyword">private</span> String avatar;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>GsonFormatPlus GitHub 地址：</p><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/mars-men/GsonFormatPlus"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=mars-men&repo=GsonFormatPlus&theme=onedark&show_owner=true"/></a><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>像这种毫无业务逻辑，毫无技术水平的就应该巧妙的使用工具，以节约时间来摸🐟，岂不美哉~🎉</p>]]></content>
    
    
    <summary type="html">一般后端程序员经常会有封装一些调用第三方接口的需求，这些第三方接口的参数和返回值都是提供方定义好的了，我们封装时需要自己手动来生成 POJO 类，像这种一点技术含量都没有的东西，谁都不想手动生成。</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Json" scheme="https://blog.imzjw.cn/tags/Json/"/>
    
    <category term="Java" scheme="https://blog.imzjw.cn/tags/Java/"/>
    
  </entry>
  
  <entry>
    <title>Telegram 创建一个私聊 Bot</title>
    <link href="https://blog.imzjw.cn/posts/75dadae5/"/>
    <id>https://blog.imzjw.cn/posts/75dadae5/</id>
    <published>2021-04-25T02:05:18.000Z</published>
    <updated>2021-04-25T02:05:18.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><p>本文章是针对那些 Telegram 是 +86 用户和在意自己隐私问题所记录的一篇教程。</p><p>看完本章教程之后，用户就可以和你所创建的机器人聊天，由机器人转发该用户的私聊消息，通过回复机器人所转发的消息即可回复用户，同时还可以减少窗口的数量且也保障了自己一定的隐私问题。</p><p>对于 +86 用户来说，基本可以满足，不过貌似可以通过 <a href="https://t.me/SpamBot">@SpamBot</a> 申诉解除限制，但万一如果你的朋友也是 +86 的话，他就不能和你联系了，你也告诉不了他可以通过 <a href="https://t.me/SpamBot">@SpamBot</a> 解除。</p><h2 id="创建机器人"><a href="#创建机器人" class="headerlink" title="创建机器人"></a>创建机器人</h2><p>点击 <a href="https://t.me/BotFather">@BotFather</a> ，通过机器人之父创建一个机器人。</p><p>向它发送 <code>/newbot</code> 指令</p><p>然后就会问你准备要给机器人起一个什么名字（随意，可以中文）</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/75dadae5/20210524222523.webp" alt="images"></p><p>接着给机器人取一个 <strong>username</strong>，不可重复，须以 <code>_bot</code> 结尾</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/75dadae5/20210524223352.webp" alt="IMAGES"></p><p>机器人如此如此就创建成功了，最后生成的那个机器人 Token，不可乱泄露。</p><h2 id="创建私聊机器人"><a href="#创建私聊机器人" class="headerlink" title="创建私聊机器人"></a>创建私聊机器人</h2><p>点击 <a href="https://t.me/LivegramBot">@LivegramBot</a> 向它发送 <code>/addbot</code> 指令，然后发送刚刚创建机器人 <strong>Token</strong>。（貌似好像有个服务条款啥的你需要先同意一下，然后再发送。）</p><p>出现 <strong>Success</strong> 则私聊机器人创建成功！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/75dadae5/20210524225156.webp" alt="IMAGES"></p><h3 id="机器人-Token-在哪？"><a href="#机器人-Token-在哪？" class="headerlink" title="机器人 Token 在哪？"></a>机器人 Token 在哪？</h3><p>给 BotFather 发送 /mybots 然后就会列出你所有的机器人，点击刚刚创建的机器人，就会有个 API Token，再点击 API Token 就出现该机器人的 Token。</p><p>其实到这就已经基本创建完毕了，但是那些描述啊，头像啊，关于啥的，都是 null，就比较简陋，因此我们可以通过 BotFather 修改机器人信息。</p><h2 id="修改机器人信息"><a href="#修改机器人信息" class="headerlink" title="修改机器人信息"></a>修改机器人信息</h2><p>给 BotFather 发送 /mybots 指令，选择私聊机器人</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/75dadae5/20210524225828.webp" alt="IMAGES"></p><p>选择 Edit Bot</p><p><strong>Edit Name</strong>：修改机器人名称<br><strong>Edit Description</strong>：修改机器人描述，它能做什么？<br><strong>Edit About</strong>：介绍一下机器人<br><strong>Edit Botpic</strong>：给机器人上传一张美美的头像，须压缩图，不能是文件。<br><strong>Edit Commands</strong>：编辑 \ 添加指令</p><p>以修改描述为例，其它的自己举一反三。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/75dadae5/20210524231154.webp" alt="IMAGES"></p><p>修改完成之后，稍等片刻，回到自己的机器人界面，即可看到刚刚那段描述！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/75dadae5/20210524231420.webp" alt="images"></p><h2 id="测试与使用"><a href="#测试与使用" class="headerlink" title="测试与使用"></a>测试与使用</h2><p>切换另一个号，私聊机器人</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/75dadae5/20210525092638.webp" alt="images"></p><p>然后机器人就会转发该用户的私聊信息</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/75dadae5/20210525093752.webp" alt="images"></p><p><strong>如何回复？</strong></p><p>你可以右键选择回复进行回复，也可以在消息右侧双击鼠标左键进行回复。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/75dadae5/reply.gif" alt="images"></p><p>这样即完成了私聊机器人的创建。</p><p>最后如果你对 Telegram Bot 感兴趣的话，可以看峰哥的 <a href="https://www.youtube.com/playlist?list=PL3dZh-p-vVofZ0BOQ4LnPlhJV3sVAQX8h">Telegram 机器人系列教学</a></p>]]></content>
    
    
    <summary type="html">本文章是针对那些 Telegram 是 +86 用户和在意自己隐私问题所记录的一篇教程。看完本章教程之后，用户就可以和你所创建的机器人聊天。</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="Telegram" scheme="https://blog.imzjw.cn/tags/Telegram/"/>
    
  </entry>
  
  <entry>
    <title>Spring Boot 集成 dynamic datasource 实现多数据源切换</title>
    <link href="https://blog.imzjw.cn/posts/8983923f/"/>
    <id>https://blog.imzjw.cn/posts/8983923f/</id>
    <published>2021-04-23T12:00:07.000Z</published>
    <updated>2021-04-23T12:00:07.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>日常开发中，可能会遇到一个项目要调用多个数据源的情况，比如同一个 MySQL 不同的库，也可能是从不同的 MySQL 进行获取数据，此时，我们可以使用 <code>dynamic datasource</code> 进行多数据源切换。</p><h2 id="dynamic-datasource-介绍"><a href="#dynamic-datasource-介绍" class="headerlink" title="dynamic datasource 介绍"></a>dynamic datasource 介绍</h2><p><code>dynamic datasource</code>  其实是 <a href="https://baomidou.com/">苞米豆</a>（也就是 MyBatis-Plus）的其中一个框架，是一个基于 Spring Boot 的快速集成多数据源的启动器。</p><p>更详细的了解，请前往 <a href="https://dynamic-datasource.com/">dynamic datasource 官网</a></p><h2 id="快速开始"><a href="#快速开始" class="headerlink" title="快速开始"></a>快速开始</h2><p>演示环境</p><ul><li>IntelliJ IDEA 2020.3.2</li><li>JDK 8</li><li>MySQL 5.7</li><li>Maven 3.6.3</li><li>Spring Boot 2.4.5</li></ul><p>SQL 准备（创建了两个库，分别是 <code>dep</code> 和 <code>emp</code>）</p><p><code>dep</code> 库下的表</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> `t_dep` (</span><br><span class="line">  `id` <span class="type">bigint</span>(<span class="number">20</span>) <span class="keyword">NOT</span> <span class="keyword">NULL</span> AUTO_INCREMENT,</span><br><span class="line">  `name` <span class="type">varchar</span>(<span class="number">50</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line">  <span class="keyword">PRIMARY</span> KEY (`id`)</span><br><span class="line">) ENGINE<span class="operator">=</span>InnoDB AUTO_INCREMENT<span class="operator">=</span><span class="number">4</span> <span class="keyword">DEFAULT</span> CHARSET<span class="operator">=</span>utf8mb4;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- ----------------------------</span></span><br><span class="line"><span class="comment">-- Records of t_dep</span></span><br><span class="line"><span class="comment">-- ----------------------------</span></span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `t_dep` <span class="keyword">VALUES</span> (<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;開發部&#x27;</span>);</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `t_dep` <span class="keyword">VALUES</span> (<span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;測試部&#x27;</span>);</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `t_dep` <span class="keyword">VALUES</span> (<span class="string">&#x27;3&#x27;</span>, <span class="string">&#x27;生產部&#x27;</span>);</span><br></pre></td></tr></table></figure><p><code>emp</code> 库下的表</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> `t_emp` (</span><br><span class="line">  `id` <span class="type">bigint</span>(<span class="number">20</span>) <span class="keyword">NOT</span> <span class="keyword">NULL</span> AUTO_INCREMENT,</span><br><span class="line">  `name` <span class="type">varchar</span>(<span class="number">50</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line">  <span class="keyword">PRIMARY</span> KEY (`id`)</span><br><span class="line">) ENGINE<span class="operator">=</span>InnoDB AUTO_INCREMENT<span class="operator">=</span><span class="number">4</span> <span class="keyword">DEFAULT</span> CHARSET<span class="operator">=</span>utf8mb4;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- ----------------------------</span></span><br><span class="line"><span class="comment">-- Records of t_emp</span></span><br><span class="line"><span class="comment">-- ----------------------------</span></span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `t_emp` <span class="keyword">VALUES</span> (<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;張三&#x27;</span>);</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `t_emp` <span class="keyword">VALUES</span> (<span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;李四&#x27;</span>);</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `t_emp` <span class="keyword">VALUES</span> (<span class="string">&#x27;3&#x27;</span>, <span class="string">&#x27;王五&#x27;</span>);</span><br></pre></td></tr></table></figure><p>然后创建 Spring Boot 项目，引入基本的 Web 依赖和 MySQL 驱动</p><p>完整的 <code>pom</code> 文件</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--dynamic datasource 核心 maven 依赖--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.baomidou<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>dynamic-datasource-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.1.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-jdbc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">scope</span>&gt;</span>runtime<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis.spring.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.1.3<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">optional</span>&gt;</span>true<span class="tag">&lt;/<span class="name">optional</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><p>编写配置文件（<code>application.yaml</code>）</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">dynamic:</span></span><br><span class="line">      <span class="attr">primary:</span> <span class="string">master</span> <span class="comment"># 设置默认的数据源或者数据源组,默认值即为 master</span></span><br><span class="line">      <span class="attr">strict:</span> <span class="literal">false</span> <span class="comment"># 设置严格模式,默认 false 不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.</span></span><br><span class="line">      <span class="attr">datasource:</span></span><br><span class="line">        <span class="attr">master:</span></span><br><span class="line">          <span class="attr">url:</span> <span class="string">jdbc:mysql:///dep</span></span><br><span class="line">          <span class="attr">username:</span> <span class="string">garvey</span></span><br><span class="line">          <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line">          <span class="attr">driver-class-name:</span> <span class="string">com.mysql.jdbc.Driver</span></span><br><span class="line">        <span class="attr">slave:</span></span><br><span class="line">          <span class="attr">url:</span> <span class="string">jdbc:mysql:///emp</span></span><br><span class="line">          <span class="attr">username:</span> <span class="string">garvey</span></span><br><span class="line">          <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line">          <span class="attr">driver-class-name:</span> <span class="string">com.mysql.jdbc.Driver</span></span><br></pre></td></tr></table></figure><p><code>dao</code> 层（因为就这么一句简单 SQL，这里就不创建 mapper 映射文件了，直接使用注解）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">DepMapper</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Select(&quot;SELECT id, name FROM t_dep&quot;)</span></span><br><span class="line">    List&lt;Dep&gt; <span class="title function_">selectAll</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">EmpMapper</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Select(&quot;SELECT id, name FROM t_emp&quot;)</span></span><br><span class="line">    List&lt;Emp&gt; <span class="title function_">selectAll</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>实体类就没什么好讲的了</p><p>然后就可以通过 <code>@DS</code> 注解进行切换数据源。</p><p><code>@DS</code> 注解可以作用在方法上也可以作用在类上，<strong>同时存在就近原则，方法上的注解优先于类上的注解</strong>。</p><table><thead><tr><th align="center">注解</th><th align="center">结果</th></tr></thead><tbody><tr><td align="center">没有 @DS</td><td align="center">默认数据源</td></tr><tr><td align="center">@DS(“dsName”)</td><td align="center">dsName 可以为组名也可以为具体某个库的名称</td></tr></tbody></table><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="meta">@DS(&quot;master&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> DepMapper depMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> EmpMapper empMapper;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> List&lt;Dep&gt; <span class="title function_">selectDepAll</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> depMapper.selectAll();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@DS(&quot;slave&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> List&lt;Emp&gt; <span class="title function_">selectEmpAll</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> empMapper.selectAll();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在启动类中加上扫描 Mapper 接口的注解，最后创建 <code>Controller</code> 进行测试</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> TestService testService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;dep&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">dep</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> testService.selectDepAll();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;emp&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">emp</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> testService.selectEmpAll();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>启动之后，打开浏览器分别访问</p><p><code>http://localhost:8080/dep</code></p><p><code>http://localhost:8080/emp</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8983923f/dep&emp.3cw81im1lxa0.webp" alt="images"></p><p>参考文档</p><ul><li><a href="https://dynamic-datasource.com/">dynamic-datasource</a></li></ul>]]></content>
    
    
    <summary type="html">日常开发中，可能会遇到一个项目要调用多个数据源的情况，比如同一个 MySQL 不同的库，也可能是从不同的 MySQL 进行获取数据，此时，我们可以使用 dynamic datasource 进行多数据源切换。</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring Boot" scheme="https://blog.imzjw.cn/tags/Spring-Boot/"/>
    
    <category term="Dynamic Datasource" scheme="https://blog.imzjw.cn/tags/Dynamic-Datasource/"/>
    
  </entry>
  
  <entry>
    <title>别再打开网页搜 Maven 依赖了，试试这款 IDEA 插件</title>
    <link href="https://blog.imzjw.cn/posts/6c17e61a/"/>
    <id>https://blog.imzjw.cn/posts/6c17e61a/</id>
    <published>2021-04-16T12:37:56.000Z</published>
    <updated>2021-04-16T12:37:56.000Z</updated>
    
    <content type="html"><![CDATA[<p>这款 IDEA 插件方便我们在 IDEA 中搜索依赖信息的工具，有时我们缺少依赖还得打开浏览器到 Maven 中央仓库找，而这款插件可以直接让你在 IDEA 开发工具查找。非常的快捷方便！</p><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>在 IDEA 中打开 <code>File | Settings | Plugins</code> 搜索 <code>search in repository</code> 并安装</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/6c17e61a/searchinrepository.tjfdmmlv1r4.webp" alt="search in repository"></p><p>安装成功之后在右侧就会出现个 <code>search</code> 的工具栏，我们点击它，然后输入关键词，比如 <code>spring-boot</code> 并回车</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/6c17e61a/123.6pjynyk80zg0.webp" alt="images"></p><p>可以看到，关于 <code>spring-boot</code> 的依赖信息都列出来了，此外我们还可以点击 <code>Prev</code> 和 <code>Next</code> 按钮切换分页。</p><p>接着双击 <code>2.4.4</code> 版本，然后 Maven 和 Gradle 的依赖信息都展现出来了，点击 <code>Copy</code> 即可复制粘贴到我们的 <code>pom</code> 文件中</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/6c17e61a/xxx.60wpc41fvvg0.webp" alt="images"></p><table><thead><tr><th align="left">对比 Maven 中央仓库，Usages 和 Date 都是一模一样</th><th></th></tr></thead><tbody><tr><td align="left"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/6c17e61a/central_warehouse.1l323dxbtim8.webp" alt="images"></td><td><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/6c17e61a/p.5x9jsgikcfk0.webp" alt="images"></td></tr></tbody></table><p>而且我们还可以搜 <code>npm</code> 包</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/6c17e61a/npm.6sh0v4w6dkk0.webp" alt="npm"></p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>这款插件确实的快捷方便，但是这插件开发到现在还不足一个月，可能会遇到 BUG</p><p>比如：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/6c17e61a/bug.21evz7b4z4xs.gif" alt="bug"></p><p>GitHub 地址：</p><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/Kimentanm/search-in-repo"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=Kimentanm&repo=search-in-repo&theme=onedark&show_owner=true"/></a>]]></content>
    
    
    <summary type="html">这款 IDEA 插件方便我们在 IDEA 中搜索依赖信息的工具，有时我们缺少依赖还得打开浏览器到 Maven 中央仓库找，而这款插件可以直接让你在 IDEA 开发工具查找。非常的快捷方便！</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="IntelliJ IDEA" scheme="https://blog.imzjw.cn/tags/IntelliJ-IDEA/"/>
    
  </entry>
  
  <entry>
    <title>使用 Spring AOP 实现对日志的操作</title>
    <link href="https://blog.imzjw.cn/posts/aop-log/"/>
    <id>https://blog.imzjw.cn/posts/aop-log/</id>
    <published>2021-04-14T01:40:17.000Z</published>
    <updated>2021-04-14T01:40:17.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>AOP（Aspect Oriented Programming），被称为面向切面编程。AOP 基于 IoC 基础，是对 OOP 的有益补充，流行的 AOP 框架有 Sping AOP、AspectJ。</p><p>AOP 技术它利用一种称为横切的技术，剖解开封装的对象内部，并将那些影响了多个类的公共行为封装到一个可重用模块，并将其命名为 Aspect，即切面。所谓切面，简单说就是那些与业务无关，却为业务模块所共同调用的逻辑或责任封装起来，便于减少系统的重复代码，降低模块之间的耦合度，并有利于未来的可操作性和可维护性。</p><h2 id="AOP-核心概念"><a href="#AOP-核心概念" class="headerlink" title="AOP 核心概念"></a>AOP 核心概念</h2><ul><li><p>切面（Aspect）</p><p>散落在系统各处的通用的业务逻辑代码，如上图中的日志模块，权限模块，事务模块等，切面用来装载 pointcut 和 advice</p></li><li><p>通知（Advice）</p><p>所谓通知指的就是指拦截到连接点之后要执行的代码，通知分为前置、后置、异常、最终、环绕通知五类</p></li><li><p>连接点（Join Point）</p><p>被拦截到的点，因为 Spring 只支持方法类型的连接点，所以在 Spring 中连接点指的就是被拦截到的方法，实际上连接点还可以是字段或者构造器</p></li><li><p>切入点（Pointcut）</p><p>拦截的方法，连接点拦截后变成切入点</p></li><li><p>目标对象（Target Object）</p><p>代理的目标对象，指要织入的对象模块</p></li><li><p>织入（Weaving）</p><p>通过切入点切入，将切面应用到目标对象并导致代理对象创建的过程</p></li><li><p>AOP 代理（AOP Proxy）</p><p>AOP 框架创建的对象，包含通知。在 Spring 中，AOP 代理可以是 JDK 动态代理或 CGLIB 代理</p></li></ul><h2 id="应用场景"><a href="#应用场景" class="headerlink" title="应用场景"></a>应用场景</h2><ol><li>Authentication 权限</li><li>Caching 缓存</li><li>Context passing 内容传递</li><li>Error handing 错误处理</li><li>Lazy loding 懒加载</li><li>Debugging 调试</li><li>logging,tracing,profiling and monitoring 记录 跟踪 优化 校准</li><li>Performance optimzation 性能优化</li><li>Persistence 持久化</li><li>Resource pooling 资源池</li><li>Synchronization 同步</li><li>Transaction 事务</li></ol><h2 id="通知类型"><a href="#通知类型" class="headerlink" title="通知类型"></a>通知类型</h2><ul><li>Before Advice（前置通知）：在某连接点（Join Point）之前执行的通知，但这个通知不能阻止连接点前的执行</li><li>After Advice（后置通知）：当某连接点退出的时候执行的通知（不论是正常返回还是异常退出）</li><li>After Return advice（正常返回通知）：在某连接点正常完成后执行的通知，不包括抛出异常的情况。（如果连接点抛出异常，则不会执行。）</li><li>After throwing Advice（异常通知）：在连接点抛出异常后执行</li><li>Around advice（环绕通知）：环绕通知围绕在连接点前后，比如一个方法调用的前后。这是最强大的通知类型，能在方法调用前后自定义一些操作。</li></ul><h2 id="AOP-的两种代理方式"><a href="#AOP-的两种代理方式" class="headerlink" title="AOP 的两种代理方式"></a>AOP 的两种代理方式</h2><p>Spring 提供了两种方式生成代理对象：JDKProxy 和 Cglib，具体使用哪种方式生成由 AopProxyFactory 根据 AdvisedSupport 对象的配置决定。默认的策略是如果目标类是接口，则使用 JDK 动态代理技术，否则使用 Cglib 来生成代理。</p><ol><li><p>JDK 动态接口代理</p><p>JDK 动态代理只要涉及到 <code>Java.lang.reflect</code> 包中的两个类：Proxy 和 InvocationHandler。InvocationHandler 是一个接口，通过实现接口定义横切逻辑，并通过反射机制调用目标代码，动态将横切逻辑和业务逻辑编制在一起。Proxy 利用 InvocationHandler 动态创建一个符合某一接口的实例，生成目标类的代理对象</p></li><li><p>CGLIB 动态代理</p><p>CGLIB 全称为 Code Generation Libraay，是一个强大的高性能，高质量的代码生成类库，可以在运行期间扩展 Java 类与实现 Java 接口，CGLIB 封装了 <code>asm</code>，可以在运行期间生成新的 Class。和 JDK 动态代理相比较：JDK 创建代理又一个限制，就是只能为创建对象代理实例，而没有通过接口定义业务方法的类，则通过 CGLIB 创建动态代理。</p></li></ol><p>废话好像有点多了，那开始正文把…</p><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>首先创建 Spring Boot 工程，Spring Boot 版本我用的是 2.4.4</p><p>添加依赖（pom.xml）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-aop<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- slf4j --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.slf4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>slf4j-api<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-jdbc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- mysql驱动 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis.spring.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.1.3<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><p>创建 SQL（我准备了 SQL 语句）</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> `sys_log` (</span><br><span class="line">  `id` <span class="type">bigint</span>(<span class="number">20</span>) <span class="keyword">NOT</span> <span class="keyword">NULL</span> AUTO_INCREMENT,</span><br><span class="line">  `username` <span class="type">varchar</span>(<span class="number">255</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line">  `operation` <span class="type">varchar</span>(<span class="number">255</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line">  `<span class="type">time</span>` <span class="type">int</span>(<span class="number">11</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line">  `<span class="keyword">method</span>` <span class="type">varchar</span>(<span class="number">255</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line">  `params` <span class="type">varchar</span>(<span class="number">255</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line">  `ip` <span class="type">varchar</span>(<span class="number">255</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line">  `createTime` datetime <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line">  <span class="keyword">PRIMARY</span> KEY (`id`)</span><br><span class="line">) ENGINE<span class="operator">=</span>InnoDB <span class="keyword">DEFAULT</span> CHARSET<span class="operator">=</span>utf8;</span><br></pre></td></tr></table></figure><p>配置 yml 文件</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># 数据库配置</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">jdbc:mysql:///aop_demo?useUnicode=true&amp;characterEncoding=utf-8</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">xiaojia</span></span><br><span class="line">    <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line"></span><br><span class="line"><span class="attr">mybatis:</span></span><br><span class="line">  <span class="attr">type-aliases-package:</span> <span class="string">cn.imzjw.entity</span>     <span class="comment"># 开启别名</span></span><br><span class="line">  <span class="attr">mapper-locations:</span> <span class="string">classpath:mapper/*.xml</span>  <span class="comment"># 映射文件路径</span></span><br><span class="line">  <span class="attr">configuration:</span></span><br><span class="line">    <span class="attr">log-impl:</span> <span class="string">org.apache.ibatis.logging.stdout.StdOutImpl</span> <span class="comment"># 开启日志</span></span><br></pre></td></tr></table></figure><p>自定义一个注解（<code>Log.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Target(ElementType.METHOD)</span></span><br><span class="line"><span class="meta">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> Log &#123;</span><br><span class="line"></span><br><span class="line">    String <span class="title function_">value</span><span class="params">()</span> <span class="keyword">default</span> <span class="string">&quot;&quot;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>创建实体类（<code>SysLog.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SysLog</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">serialVersionUID</span> <span class="operator">=</span> -<span class="number">6309732882044872298L</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 用户名</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String username;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 操作</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String operation;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 执行时间（ms 单位）</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> Integer time;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 操作方法</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String method;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 参数</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String params;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * ip</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String ip;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 创建时间</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> Date createTime;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>创建 Mapper 接口（<code>SysLogMapper.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">SysLogMapper</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">saveSysLog</span><span class="params">(SysLog syslog)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>创建映射文件（<code>src/main/resources/mapper/SysLogMapper.xml</code>）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">mapper</span> <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span> <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;cn.imzjw.mapper.SysLogMapper&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">insert</span> <span class="attr">id</span>=<span class="string">&quot;saveSysLog&quot;</span>&gt;</span></span><br><span class="line">        INSERT INTO sys_log(username, operation, time, method, params, ip, createTime)</span><br><span class="line">        VALUES (#&#123;username&#125;, #&#123;operation&#125;, #&#123;time&#125;, #&#123;method&#125;, #&#123;params&#125;, #&#123;ip&#125;, #&#123;createTime&#125;)</span><br><span class="line">    <span class="tag">&lt;/<span class="name">insert</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure><p>创建日志记录 AOP 实现（<code>LogAspect.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogAspect</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> SysLogMapper sysLogMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Pointcut(&quot;@annotation(cn.imzjw.anno.Log)&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">pointcut</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Around(&quot;pointcut()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">around</span><span class="params">(ProceedingJoinPoint point)</span> &#123;</span><br><span class="line">        <span class="type">long</span> <span class="variable">beginTime</span> <span class="operator">=</span> System.currentTimeMillis();</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 执行方法</span></span><br><span class="line">            point.proceed();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Throwable e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 执行时长(ms 单位)</span></span><br><span class="line">        <span class="type">long</span> <span class="variable">time</span> <span class="operator">=</span> System.currentTimeMillis() - beginTime;</span><br><span class="line">        <span class="comment">// 保存日志</span></span><br><span class="line">        saveLog(point, time);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">saveLog</span><span class="params">(ProceedingJoinPoint joinPoint, <span class="type">long</span> time)</span> &#123;</span><br><span class="line">        <span class="type">MethodSignature</span> <span class="variable">signature</span> <span class="operator">=</span> (MethodSignature) joinPoint.getSignature();</span><br><span class="line">        <span class="type">Method</span> <span class="variable">method</span> <span class="operator">=</span> signature.getMethod();</span><br><span class="line">        <span class="type">SysLog</span> <span class="variable">sysLog</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SysLog</span>();</span><br><span class="line">        <span class="type">Log</span> <span class="variable">logAnnotation</span> <span class="operator">=</span> method.getAnnotation(Log.class);</span><br><span class="line">        <span class="keyword">if</span> (logAnnotation != <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="comment">// 注解上的描述</span></span><br><span class="line">            sysLog.setOperation(logAnnotation.value());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 请求的方法名</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">className</span> <span class="operator">=</span> joinPoint.getTarget().getClass().getName();</span><br><span class="line">        <span class="type">String</span> <span class="variable">methodName</span> <span class="operator">=</span> signature.getName();</span><br><span class="line">        sysLog.setMethod(className + <span class="string">&quot;.&quot;</span> + methodName + <span class="string">&quot;()&quot;</span>);</span><br><span class="line">        <span class="comment">// 请求的方法参数值</span></span><br><span class="line">        Object[] args = joinPoint.getArgs();</span><br><span class="line">        <span class="comment">// 请求的方法参数名称</span></span><br><span class="line">        <span class="type">LocalVariableTableParameterNameDiscoverer</span> <span class="variable">u</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">LocalVariableTableParameterNameDiscoverer</span>();</span><br><span class="line">        String[] paramNames = u.getParameterNames(method);</span><br><span class="line">        <span class="keyword">if</span> (args != <span class="literal">null</span> &amp;&amp; paramNames != <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">params</span> <span class="operator">=</span> <span class="string">&quot;&quot;</span>;</span><br><span class="line">            <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; args.length; i++) &#123;</span><br><span class="line">                params += <span class="string">&quot;  &quot;</span> + paramNames[i] + <span class="string">&quot;: &quot;</span> + args[i];</span><br><span class="line">            &#125;</span><br><span class="line">            sysLog.setParams(params);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 获取 request</span></span><br><span class="line">        <span class="type">HttpServletRequest</span> <span class="variable">request</span> <span class="operator">=</span> HttpContextUtils.getHttpServletRequest();</span><br><span class="line">        <span class="comment">// 设置 IP 地址</span></span><br><span class="line">        sysLog.setIp(IPUtils.getIpAddr(request));</span><br><span class="line">        <span class="comment">// 模拟一个用户名</span></span><br><span class="line">        sysLog.setUsername(<span class="string">&quot;garvey&quot;</span>);</span><br><span class="line">        sysLog.setTime((<span class="type">int</span>) time);</span><br><span class="line">        <span class="type">Date</span> <span class="variable">date</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Date</span>();</span><br><span class="line">        sysLog.setCreateTime(date);</span><br><span class="line">        <span class="comment">// 保存到数据库中</span></span><br><span class="line">        sysLogMapper.saveSysLog(sysLog);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>创建 <code>Controller</code> 测试</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DemoController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 测试带有参数的方法</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> name 名称</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Log(&quot;测试带有参数的方法&quot;)</span></span><br><span class="line">    <span class="meta">@GetMapping(&quot;/demo&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">demo</span><span class="params">(String name)</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>最后别忘了在启动类上加上扫描 Mapper 接口的注解</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="meta">@MapperScan(&quot;cn.imzjw.mapper&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AopLogApplication</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        SpringApplication.run(AopLogApplication.class, args);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>打开浏览器访问 <code>http://localhost:8080/demo?name=xiaojia</code></p><p>然后查看数据库</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/aop-log/log.4f70j862in40.webp" alt="log"></p><p>至此，使用 Spring AOP 实现对日志的操作就大功告成了！</p>]]></content>
    
    
    <summary type="html">AOP（Aspect Oriented Programming），被称为面向切面编程。AOP 基于 IoC 基础，是对 OOP 的有益补充，流行的 AOP 框架有 Sping AOP、AspectJ。AOP 技术它利用一种称为横切的技术</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring" scheme="https://blog.imzjw.cn/tags/Spring/"/>
    
  </entry>
  
  <entry>
    <title>Spring Boot 配置多环境</title>
    <link href="https://blog.imzjw.cn/posts/a74c63b3/"/>
    <id>https://blog.imzjw.cn/posts/a74c63b3/</id>
    <published>2021-04-09T09:59:12.000Z</published>
    <updated>2021-04-09T09:59:12.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>我们日常开发中，一般都会配置多个环境，比如开发环境（dev）、生产环境（prod）、测试环境（test），不然因为众多的配置，众多的参数，什么 Redis、MySQL、注册中心的配置，都在一个环境的配置文件下，就会很头疼，而 Spring Boot 的多环境配置就很好的解决了这一个问题，把<emp>不同环境</emp>的<emp>不同参数</emp>配置在<emp>不同的配置文件</emp>里，哪里需要就配置加载哪个配置文件就可以了。</p><h2 id="各环境区别"><a href="#各环境区别" class="headerlink" title="各环境区别"></a>各环境区别</h2><ul><li><p><strong>开发环境</strong></p><p>顾名思义，开发同学开发时使用的环境，每位开发同学在自己的 dev 分支上干活，提测前或者开发到一定程度，各位同学会合并代码，进行联调。</p></li><li><p><strong>测试环境</strong></p><p>也就是我们测试同学干活的环境，一般是克隆一份生产环境的配置，一个程序在测试环境工作不正常，那么肯定不能把它发布到生产机上。</p></li><li><p><strong>生产环境</strong></p><p>即线上环境，用户使用的环境。</p></li></ul><h2 id="演示环境"><a href="#演示环境" class="headerlink" title="演示环境"></a>演示环境</h2><ul><li>Spring Boot 2.3.0.RELEASE</li><li>IntelliJ IDEA 2020.3.2</li></ul><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>首先我们需要创建一个 Spring Boot 工程</p><h3 id="方式一"><a href="#方式一" class="headerlink" title="方式一"></a>方式一</h3><div class="note success flat"><p>同一个配置文件配置多个环境</p></div><p>打开 <code>application.yml</code> 配置文件，添加如下配置</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 主配置</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">profiles:</span></span><br><span class="line">    <span class="comment"># 选择环境</span></span><br><span class="line">    <span class="attr">active:</span> <span class="string">dev</span></span><br><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="comment"># 开发环境</span></span><br><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="comment"># 端口</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8080</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># 配置开发环境的名称</span></span><br><span class="line">  <span class="attr">profiles:</span> <span class="string">dev</span></span><br><span class="line"></span><br><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="comment"># 测试环境</span></span><br><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="comment"># 端口</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8081</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># 配置测试环境的名称</span></span><br><span class="line">  <span class="attr">profiles:</span> <span class="string">test</span></span><br></pre></td></tr></table></figure><p>这里我选择了 dev（开发）环境，然后我把开发环境的端口设为 8080，测试环境 8081，接着我们直接启动项目来看下效果</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/a74c63b3/console.7ke57d7wj400.webp" alt="console"></p><p>通过控制台日志输出可以看出，运行的环境正是我们开发环境</p><h3 id="方式二"><a href="#方式二" class="headerlink" title="方式二"></a>方式二</h3><div class="note success flat"><p>创建多个配置文件</p></div><p>首先另外再创建两个配置文件，分别是 <code>application-dev.yml</code> 表示开发环境的配置，<code>application-test.yml</code> 表示测试环境的配置。</p><p><code>application-dev.yml</code> 配置如下</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 开发环境</span></span><br><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="comment"># 端口</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8080</span></span><br></pre></td></tr></table></figure><p><code>application-test.yml</code> 配置如下</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 测试环境</span></span><br><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="comment"># 端口</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">8081</span></span><br></pre></td></tr></table></figure><p>接着修改主配置内容（<code>application.yml</code>）</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 主配置</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">profiles:</span></span><br><span class="line">    <span class="comment"># 选择环境</span></span><br><span class="line">    <span class="attr">active:</span> <span class="string">test</span></span><br></pre></td></tr></table></figure><p>选择了测试环境，启动项目看效果</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/a74c63b3/xxx.23d3cnt3h2v4.webp" alt="images"></p><p>可以看到已是测试环境，说明这种方式也可以配置成功！</p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>通过修改 <code>application.yml</code> 文件中的 <code>spring.profiles.active</code> 参数决定加载对应环境的配置！</p>]]></content>
    
    
    <summary type="html">我们日常开发中，一般都会配置多个环境，比如开发环境（dev）、生产环境（prod）、测试环境（test），不然因为众多的配置，众多的参数，什么 Redis、MySQL、注册中心的配置，都在一个环境的配置文件下，就会很头疼</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring Boot" scheme="https://blog.imzjw.cn/tags/Spring-Boot/"/>
    
  </entry>
  
  <entry>
    <title>Windows 环境下搭建 Maven 私有仓库（私服）</title>
    <link href="https://blog.imzjw.cn/posts/nexus-config/"/>
    <id>https://blog.imzjw.cn/posts/nexus-config/</id>
    <published>2021-04-06T11:03:32.000Z</published>
    <updated>2021-04-06T11:03:32.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>私服是指私有服务器，是在局域网的一种特殊的远程仓库，目的就是代理远程仓库及部署第三方构建，有了私服之后，当 Maven 需要下载构件时，直接请求私服，私服上存在则下载到本地仓库，否则，私服将请求外部的远程仓库，将构件下载到私服，在提供给本地仓库下载。</p><h2 id="Nexus-介绍"><a href="#Nexus-介绍" class="headerlink" title="Nexus 介绍"></a>Nexus 介绍</h2><p>nexus 是一个强大的 Maven 仓库管理器，可以做私服，它极大的简化了本地内部仓库的维护和外部仓库的访问。</p><p>nexus 是一套开箱即用的系统，不需要数据库，它使用文件系统加 Lucene 来组织数据。</p><p>支持 WebDAV 与 LDAP 安全身份认证。</p><p>提供了强大的仓库管理功能，构件搜索功能。</p><h2 id="搭建步骤"><a href="#搭建步骤" class="headerlink" title="搭建步骤"></a>搭建步骤</h2><p>首先下载安装包，官网地址：<a href="https://www.sonatype.com/product/repository-oss-download">https://www.sonatype.com/product/repository-oss-download</a></p><p>在国内，可能会打不开，或者下载龟速，所以提供了安装包！</p><p>nexus-3.30.0-01-win64.zip</p><div class="btns rounded grid5">            <a class="button" href='https://odpan.ml/Software/Windows/Develop/Nexus/nexus-3.30.0-01-win64.zip' title='下载地址'><i class='fas fa-download'></i>下载地址</a>          </div><p>下载完成之后进行解压到任意磁盘，无需安装</p><p>进入 bin 目录下运行 cmd</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/directory.1vczjp9484io.webp" alt="directory"></p><p>输入 <code>nexus /run</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/cmd.4444xqrz7bw0.webp" alt="cmd"></p><p>启动成功之后打开浏览器访问 <code>http://localhost:8081/</code>，默认端口是 8081，修改端口在 <code>nexus-3.30.0-01\etc\nexus-default.properties</code> 文件</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/jksdi.3ia00p4f51k0.webp" alt="images"></p><p>初始化完成之后点击 <code>Sign in</code> 登陆，默认账号是 <code>admin</code>，默认密码在 <code>sonatype-work\nexus3</code> 下的 <code>admin.password</code> 文件</p><p>登录成功之后会要求你重新设置一个新的密码</p><p>接着添加阿里云仓库，如图</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/add-aliyun.nbipyfyluq8.webp" alt="add-aliyun"></p><p>在页面取名叫 <code>aliyun-repository</code>（建议用 a 开头，这样字母排序它就排第一位）</p><p>URL 输入：<code>http://maven.aliyun.com/nexus/content/groups/public/</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/image.2f59xqh2cuv4.webp" alt="images"></p><p>其它不用管，默认即可，最后点击创建！</p><p>接着点击 <code>maven-public</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/maven-public.4vqx301nck80.webp" alt="maven-public"></p><p>双击 <code>aliyun-repository</code> 移到右侧最后保存！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/xxx.2vn7lbxa7mk0.webp" alt="xxx"></p><p>nexus 搭建完成！</p><h2 id="配置-Maven"><a href="#配置-Maven" class="headerlink" title="配置 Maven"></a>配置 Maven</h2><p>在 <code>setting.xml</code> 文件里的 <code>&lt;servers&gt;</code> 标签内加入以下配置（<code>password</code> 是你设置的密码）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">server</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--正式版--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">id</span>&gt;</span>nexus-releases<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">username</span>&gt;</span>admin<span class="tag">&lt;/<span class="name">username</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">password</span>&gt;</span>qwe<span class="tag">&lt;/<span class="name">password</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">server</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">server</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--快照版--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">id</span>&gt;</span>nexus-snapshots<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">username</span>&gt;</span>admin<span class="tag">&lt;/<span class="name">username</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">password</span>&gt;</span>qwe<span class="tag">&lt;/<span class="name">password</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">server</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="打包发布到私服"><a href="#打包发布到私服" class="headerlink" title="打包发布到私服"></a>打包发布到私服</h2><p>在你项目里的 <code>pom.xml</code> 中加入以下配置（其中 id 对应 <code>setting.xml</code> 中的 server id）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">distributionManagement</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">repository</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">id</span>&gt;</span>nexus-releases<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">name</span>&gt;</span>Demo Release<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">url</span>&gt;</span>http://127.0.0.1:8081/repository/maven-releases<span class="tag">&lt;/<span class="name">url</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">repository</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">distributionManagement</span>&gt;</span></span><br></pre></td></tr></table></figure><p>然后先点击 clean，按住 CTRL 键再点击 deploy，最后点击上方运行按钮！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/khasdwsd.xuiacc9pk9c.webp" alt="images"></p><p>不幸的是，报 400 错误</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.8.2:deploy (default-deploy) on project ssm-book: Failed to deploy artifacts: Could not transfer artifact org.example:ssm-book:war:1.0-20210406.103711-1 from/to nexus-releases (http://127.0.0.1:8081/repository/maven-releases): Transfer failed for http://127.0.0.1:8081/repository/maven-releases/org/example/ssm-book/1.0-SNAPSHOT/ssm-book-1.0-20210406.103711-1.war 400 Repository version policy: RELEASE does not allow version: 1.0-20210406.103711-1</span><br></pre></td></tr></table></figure><p>对于 400 错误，网上的解决办法有如下</p><p>选择 Security 下的 Anonymous Access，将 Username 改为 admin</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/admin.62mfv5vhhiw0.webp" alt="images"></p><p>点击 <code>maven-releases</code> 把 Deployment policy 改为 Allow redeploy，最后保存即可（这个作用就是允许重新部署，比如已存在的 jar 包，是不能再重新部署的）</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/release.9b379cfuxp8.webp" alt="images"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/xxx.6w20fdetrgo0.webp" alt="xxx"></p><p>还有一种是版本问题，就是你不能发布 <code>SNAPSHOT</code>（快照） 版本到 Release 类型的仓库，查看 <code>pom.xml</code>，看看是不是 <code>SNAPSHOT</code> 版本，然后修改它！</p><p>最后发布成功！熟悉的 <code>BUILD SUCCESS</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/xxx.4f92z0j76y60.webp" alt="BUILD SUCCESS"></p><p>最后我们可以查看已发布的包</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/cat.11q70vi5uj9.webp" alt="images"></p><p>我们还可以使用私服中的 jar 包</p><p>在 <code>pom.xml</code> 添加</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">repositories</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">repository</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">id</span>&gt;</span>nexus<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">name</span>&gt;</span>Demo Repository<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">url</span>&gt;</span>http://127.0.0.1:8081/repository/maven-public/<span class="tag">&lt;/<span class="name">url</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">releases</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">enabled</span>&gt;</span>true<span class="tag">&lt;/<span class="name">enabled</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">releases</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">snapshots</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">enabled</span>&gt;</span>true<span class="tag">&lt;/<span class="name">enabled</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">snapshots</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">repository</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">repositories</span>&gt;</span></span><br></pre></td></tr></table></figure><p>不仅要指定 repositories 的 <code>url</code>，我们还要在 dependencies 标签加入依赖</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>cn.imzjw<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>ssm-book<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><p>这时候私服中的 <code>jar</code> 包就已经下载到本地了！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/nexus-config/download.5ugq0h256q40.webp" alt="local"></p><div class="note success flat"><p>至此，一个简单的搭建及上传就大功告成了！</p></div>]]></content>
    
    
    <summary type="html">私服是指私有服务器，是在局域网的一种特殊的远程仓库，目的就是代理远程仓库及部署第三方构建，有了私服之后，当 Maven 需要下载构件时，直接请求私服，私服上存在则下载到本地仓库</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Nexus" scheme="https://blog.imzjw.cn/tags/Nexus/"/>
    
  </entry>
  
  <entry>
    <title>用 Gradle 简单构建 Spring Boot 项目</title>
    <link href="https://blog.imzjw.cn/posts/ee70a59e/"/>
    <id>https://blog.imzjw.cn/posts/ee70a59e/</id>
    <published>2021-03-31T11:02:40.000Z</published>
    <updated>2021-03-31T11:02:40.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Gradle 是基于 Apache Ant 和 Apache Maven 概念的项目自动化建构工具，在语法上是基于 Groovy 语言的，被广泛地运用到了 Android 开发中，但是在 Java 中，用 Maven 作为构建工具的还是比较多，但也只是暂时！就连 Spring Boot 在 2.3.0 版本中放弃 Maven，使用 Gradle 构建！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/ee70a59e/images.3xwx3cb8c5q0.webp" alt="images"></p><p>下面就开始进行构建。</p><h2 id="演示环境"><a href="#演示环境" class="headerlink" title="演示环境"></a>演示环境</h2><ul><li>Spring Boot 2.4.4</li><li>Java 8</li><li>IntelliJ IDEA 2020.3.2</li><li>Gradle 6.8.3</li></ul><p>首先得下载 Gradle</p><div class="btns rounded grid5">            <a class="button" href='https://gradle.org/releases/' title='下载地址'><i class='fas fa-download'></i>下载地址</a>          </div><p>个人喜欢下载完整版本，这样点进源码会有注释！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/ee70a59e/installation_package.1btd3a7q57i8.webp" alt="download_gradle"></p><p>下载完成之后解压到任意磁盘，随后打开 idea 开发工具，先配置 gradle</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/ee70a59e/gradle_config.1pz40vw1hlgg.webp" alt="gradle_config"></p><p>在 <code>File | Settings | Build, Execution, Deployment | Build Tools | Gradle</code> 配置本地 gradle 仓库</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/ee70a59e/20210331175933.6k2jj72uasg0.webp" alt="gradle_repo"></p><p>然后返回进行创建 Spring Boot 项目</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/ee70a59e/CREATE_GRADLE.49eguly4wme0.webp" alt="CREATE_GRADLE"></p><p>Next 之后勾选 <code>Spring Web</code> 依赖足矣</p><p>进入项目之后，我们再进行配置一下 gradle</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/ee70a59e/gradle_config.4twul4d1xla0.webp" alt="gradle_config"></p><p>随后打开项目中的 <code>build.gradle</code>，发现有 3 个插件（你可以把 <code>build.gradle</code> 理解成 maven 中的 <code>pom.xml</code>）</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">plugins &#123;</span><br><span class="line">    id <span class="string">&#x27;org.springframework.boot&#x27;</span> version <span class="string">&#x27;2.4.4&#x27;</span></span><br><span class="line">    id <span class="string">&#x27;io.spring.dependency-management&#x27;</span> version <span class="string">&#x27;1.0.11.RELEASE&#x27;</span></span><br><span class="line">    id <span class="string">&#x27;java&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>大致讲下：</strong></p><ul><li><p><code>org.springframework.boot</code></p><p>很明显，这是 Spring Boot 官方提供的 Gradle 插件，我们可以修改 <code>version</code> 来指定 Spring Boot 的版本</p></li><li><p><code>io.spring.dependency-management</code></p><p>就是管理依赖的插件，相当于在 Maven 中的 <code>dependencyManagement</code></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependencyManagement</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>commons-io<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>commons-io<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencyManagement</span>&gt;</span></span><br></pre></td></tr></table></figure><p>这样的话我在子模块中引入的时候，就不用再填写版本号了，好处就是可以统一依赖版本！</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>commons-io<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>commons-io<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><p>gradle 中的写法如下，相比 maven，简洁了许多！</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">dependencyManagement &#123;</span><br><span class="line">    dependencies &#123;</span><br><span class="line">        dependency <span class="string">&#x27;commons-io:commons-io:2.5&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">dependencies &#123;</span><br><span class="line">    implementation <span class="string">&#x27;commons-io:commons-io&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p><code>java</code></p><p>Java 项目呗，大概就是编译 Java 的（个人理解）</p></li></ul><p>然后创建一个控制器</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelloGradleController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;hello&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">demo</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;Hello Gradle 💋&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行主程序，访问 <code>http://localhost:8080/hello</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/ee70a59e/hello.74c5sh4yfo40.webp" alt="hello"></p><p>最后，我们可以配置阿里镜像使得加速</p><p>只在当前项目生效，就在 <code>build.gradle</code> 添加如下配置</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">repositories &#123;</span><br><span class="line">    maven &#123;</span><br><span class="line">        url <span class="string">&quot;http://maven.aliyun.com/nexus/content/groups/public&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>配置全局生效</p><p>在 <code>用户目录下/.gradle/init.gradle</code> 文件，如果没有，自己创建一个，添加如下配置</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">allprojects &#123;</span><br><span class="line">    repositories &#123;</span><br><span class="line">        maven &#123;</span><br><span class="line">            url <span class="string">&quot;http://maven.aliyun.com/nexus/content/groups/public&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>验证是否配置成功</p><p>在 <code>build.gradle</code> 添加一个任务</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">task queryRepos &#123;</span><br><span class="line">    doLast &#123;</span><br><span class="line">        repositories.each &#123;</span><br><span class="line">            println <span class="string">&quot;repository: $&#123;it.name&#125; (&#x27;$&#123;it.url&#125;&#x27;)&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后 <code>cmd</code> 执行 <code>gradle -q queryRepos</code>，如果显示刚刚配置的地址就说明配置成功</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">repository: maven (<span class="string">&#x27;http://maven.aliyun.com/nexus/content/groups/public/&#x27;</span>)</span><br></pre></td></tr></table></figure><p>如果提示 gradle 不是内部或外部命令，也不是可运行的程序，自行谷歌配置环境变量！</p><p>至此，简单的构建就结束了！</p>]]></content>
    
    
    <summary type="html">Gradle 是基于 Apache Ant 和 Apache Maven 概念的项目自动化建构工具，在语法上是基于 Groovy 语言的，被广泛地运用到了 Android 开发中，但是在 Java 中，用 Maven 作为构建工具的还是比较多，但也是暂时！</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring Boot" scheme="https://blog.imzjw.cn/tags/Spring-Boot/"/>
    
    <category term="Gradle" scheme="https://blog.imzjw.cn/tags/Gradle/"/>
    
  </entry>
  
  <entry>
    <title>书签多的人真的需要搭个导航网</title>
    <link href="https://blog.imzjw.cn/posts/37170000000000000000/"/>
    <id>https://blog.imzjw.cn/posts/37170000000000000000/</id>
    <published>2021-03-29T13:30:26.000Z</published>
    <updated>2021-04-28T11:12:32.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>我们在浏览网站时，发现不错的网站就会 <kbd>CTRL</kbd> + <kbd>D</kbd> 加入到书签，但是书签多起来就不是很好管理，而且还有局限性，比如我在 <code>Google Chrome</code> 收藏的书签，万一我用 <code>Microsoft Edge Browser</code> 呢，虽然可以导入，但是挺麻烦的，某天我又添加书签呢…</p><p>于是，我便开始寻找导航网源码，这样不管用哪个浏览器，直接打开我的导航网站！</p><h2 id="WebStack"><a href="#WebStack" class="headerlink" title="WebStack"></a>WebStack</h2><p><a href="https://github.com/WebStackPage/WebStackPage.github.io">GitHub 地址</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/Webstack.2j26epelj2a0.webp" alt="Webstack"></p><p>无后台的纯静态导航，可以利用静态托管平台搭建，当然，也有很多大佬开发出不同的版本，也包括有后台的，而我就用过懒人开发出的 Hexo 主题 <a href="https://github.com/HCLonely/hexo-theme-webstack">hexo-theme-webstack</a>，怎么说呢，就是添加书签的时候太麻烦了。</p><h2 id="WebStack-Pro"><a href="#WebStack-Pro" class="headerlink" title="WebStack Pro"></a>WebStack Pro</h2><p>这是 WordPress 的一款收费主题，搭建了一会  …WP 后台真心看不懂，是真的太复杂了，也就颜值还不错，最后还是放弃了</p><p>源码的话，谷歌 <a href="https://www.google.com/search?q=WebStack+Pro&newwindow=1&safe=strict&sxsrf=ALeKk01G5GTHq50xRMjMucsIeCO3IOAUig:1617020194758&ei=IsVhYJTPLfTUmAW974fgDQ&oq=WebStack+Pro&gs_lcp=Cgdnd3Mtd2l6EAMyBAgjECcyBAgjECcyAggAOgcIIxCwAxAnOgQIABAeUIgXWMkZYN0baAFwAHgAgAHMAYgBiQWSAQUwLjMuMZgBAKABAaoBB2d3cy13aXrIAQHAAQE&sclient=gws-wiz&ved=0ahUKEwiU6LXSvdXvAhV0KqYKHb33AdwQ4dUDCA0&uact=5">WebStack Pro</a> 往下拉拉应该就会出来很多去授权、pj 版之类的，但那都是 2.0406 版本的</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/webStackpro.cvl1g9merqg.webp" alt="WebStack Pro"></p><p>然后还有一些贼™  <code>low</code>  的就不说了</p><p>最后一个，也是我本人正在用的一款</p><h2 id="OneNav"><a href="#OneNav" class="headerlink" title="OneNav"></a>OneNav</h2><p><a href="https://github.com/helloxz/onenav">GitHub 地址</a></p><p><a href="https://nav.imzjw.cn/">预览地址</a></p><p>它是使用 PHP + SQLite 3 开发的一款简约导航</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/onenav.3zyyplozzze0.webp" alt="onenav"></p><p>内置两套主题，默认的就很好看（另一款主题叫 <code>webstack</code>）</p><p>我为什么选择它</p><ol><li><p>支持私有链接</p><p>也就是说，我可以把 18 岁以上的或者不想给访客看到的网站给它私有了，只有管理员登录了才可见</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/private.440lbsqxh3q0.webp" alt="private"></p></li><li><p>后台添加网站方便，它有个识别的功能，然后自动补全名称和描述</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/xxx.4byc24pdxqk0.webp" alt="images"></p></li><li><p>编辑也方便，右键书签，可编辑，删除（<strong>仅默认主题才有</strong>）</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/images1.1zdmpts1q6f4.webp" alt="images"></p></li><li><p>备份也简单，因为数据库不是用的 MySQL，所以直接打包整个站点即可！</p></li></ol><h2 id="安装-OneNav"><a href="#安装-OneNav" class="headerlink" title="安装 OneNav"></a>安装 OneNav</h2><p>OneNav 安装方法有一键部署和 Docker 安装，本文就讲在虚拟主机上安装！其它安装方式看 OneNav 文档！</p><p><a href="https://www.yuque.com/helloz/onenav/install#YzXnh">宝塔面板一键部署</a></p><p><a href="https://www.yuque.com/helloz/onenav/install#bxUfa">Docker 安装</a></p><p>安装方法大同小异！</p><p>首先到 <a href="https://github.com/helloxz/onenav/releases">GitHub - Releases</a> 把项目下载到本地，然后把文件夹内的所有文件添加到压缩包，接着随便找台虚拟主机</p><p>并把压缩包上传到 <code>wwwroot</code>，最后解压</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/unzip.309m54fjzxs0.webp" alt="images"></p><p>然后编辑根目录下的 <code>config.simple.php</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/config.4mgfq2bgzzs0.webp" alt="config"></p><p>把刚刚编辑好的 <code>config.simple.php</code> 重命名为 <code>config.php</code> 并复制一份到 <code>data</code> 目录下</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/data.653qwu1f3rk0.webp" alt="images"></p><p>如果您使用的是 <code>Nginx</code>，请务必将以下规则添加到站点配置中，否则数据库可能会被下载（虚拟主机忽略这一步）</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 安全设置</span></span><br><span class="line">location ~* ^/(class|controller|db|data|<span class="built_in">functions</span>|templates)/.*.(db3|php|php5)$ &#123;</span><br><span class="line">    <span class="built_in">return</span> 403;</span><br><span class="line">&#125;</span><br><span class="line">location /db &#123;</span><br><span class="line">    deny all;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 伪静态</span></span><br><span class="line">rewrite ^/click/(.*) /index.php?c=click&amp;<span class="built_in">id</span>=<span class="variable">$1</span> <span class="built_in">break</span>;</span><br><span class="line">rewrite ^/api/(.*)?(.*) /index.php?c=api&amp;method=<span class="variable">$1</span>&amp;<span class="variable">$2</span> <span class="built_in">break</span>;</span><br><span class="line">rewrite /login /index.php?c=login <span class="built_in">break</span>;</span><br></pre></td></tr></table></figure><p>Apache 无需配置，已内置 <code>.htaccess</code> 进行屏蔽。</p><p>最后域名解析一下打开网站即可。</p><hr><p><code>2021-04-28</code> 编辑</p><div class="note danger flat"><p>OneNav 更新到 0.9.11，支持本地书签批量导入！ 详情请到 <a href="https://github.com/helloxz/onenav/releases/tag/0.9.11">GitHub - beta 0.9.11</a> </p></div><p>还增加了第三方主题，由大佬 baisu 制作，支持黑暗模式！</p><p>简单讲下如何安装并更换，首先下载主题</p><div class="btns rounded grid5">            <a class="button" href='https://garvey.lanzoui.com/iuqTCpbkrad' title='下载地址'><i class='fas fa-download'></i>下载地址</a>          </div><p>下载成功之后把压缩包上传到 <code>templates</code> 目录下，进行解压</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/baisu.2y19nxdbmt40.webp" alt="baisu"></p><p>然后编辑 <code>data</code> 目录下的 <code>config.php</code>，修改为 <code>baisu</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/upd-baisu.5tg3dtit7mg0.webp" alt="baisu"></p><p>黑暗：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/baisu-black.5pmmz6226sw0.webp" alt="baisu-black"></p><p>浅色：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/baisu-white.4hzcl643q9i0.webp" alt="baisu-white"></p><p>还有另一款第三方主题，但是优化的不是很好，就不讲了！</p><table><thead><tr><th><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/white.6an1e6v4w1k0.webp" alt="images"></th><th align="center"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3717e16/images.m6d19ttykfk.webp" alt="images"></th></tr></thead><tbody><tr><td></td><td align="center"></td></tr></tbody></table>]]></content>
    
    
    <summary type="html">我们在浏览网站时，发现不错的网站就会 CTRL + D 加入到书签，但是书签多起来就不是很好管理，而且还有局限性，比如我在 Google Chrome 收藏的书签，万一我用 Microsoft Edge Browser 呢，虽然可以导入</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="书签" scheme="https://blog.imzjw.cn/tags/%E4%B9%A6%E7%AD%BE/"/>
    
    <category term="导航" scheme="https://blog.imzjw.cn/tags/%E5%AF%BC%E8%88%AA/"/>
    
  </entry>
  
  <entry>
    <title>Linux 宝塔面板打包部署 Vue 项目</title>
    <link href="https://blog.imzjw.cn/posts/bt-deploy-vue/"/>
    <id>https://blog.imzjw.cn/posts/bt-deploy-vue/</id>
    <published>2021-03-27T11:04:10.000Z</published>
    <updated>2021-03-29T08:14:20.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><p>有个最直接的办法就是交给静态托管平台，但是有些人就是想部署在自己服务器上，那么就可以用宝塔管理工具进行部署</p><p>本文就用 <a href="https://github.com/sl1673495/vue-netease-music">Vue 高仿网易云</a> 的项目作个演示</p><h2 id="正式开始"><a href="#正式开始" class="headerlink" title="正式开始"></a>正式开始</h2><p>本地打包好项目，所以你本地要有 <code>node</code> 环境</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build</span><br></pre></td></tr></table></figure><p>就会生成个打包后的目录，把目录下的的所有内容添加到压缩包</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/bt-deploy-vue/dist.38yqauo95xq0.webp" alt="dist"></p><p>随后连接到服务器安装宝塔</p><p><code>CentOS</code> 安装命令，其它系统参考宝塔官网的<a href="https://www.bt.cn/bbs/thread-19376-1-1.html">教程</a></p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install -y wget &amp;&amp; wget -O install.sh http://download.bt.cn/install/install_6.0.sh &amp;&amp; sh install.sh</span><br></pre></td></tr></table></figure><p>安装过程会有个选项，输入 y 回车即可</p><p>安装完成之后就会给你个外网内网地址以及用户名密码，打开浏览器输入外网地址再输入用户名密码最后同意他的协议</p><p>进入首页之后，就按他的推荐选择 <code>LNMP</code>，安装方式选择<code>极速安装</code>，然后静静等待即可！</p><p>安装完成之后，点击网站，添加站点，输入你的域名，最后提交即可</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/bt-deploy-vue/add-site.5aqeim68ge00.webp" alt="add-site"></p><p>来到文件这里，把这些默认的文件全删了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/bt-deploy-vue/image-20201217221739646.webp" alt="delete"></p><p>然后上传我们打包好的 <code>dist</code> 目录，刚刚让你添加到压缩包的那个</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/bt-deploy-vue/upload.62l5s8ax2f40.webp" alt="upload-dist"></p><p>上传成功后，解压</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/bt-deploy-vue/xxx.3986lcl3etq0.webp" alt="decompression"></p><p>最后域名解析一下大功告成！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/bt-deploy-vue/image-20201228150617547.webp" alt="success"></p><p>甚至 <code>Nginx</code> 的配置都不用配，这是因为你在添加站点的时候，宝塔就已经帮你配好了！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/bt-deploy-vue/nginx.6x09zey273s0.webp" alt="nginx"></p>]]></content>
    
    
    <summary type="html">有个最直接的办法就是交给静态托管平台，但是有些人就是想部署在自己服务器上，那么就可以用宝塔管理工具进行部署，本文就用 Vue 高仿网易云的项目作个演示</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="宝塔面板" scheme="https://blog.imzjw.cn/tags/%E5%AE%9D%E5%A1%94%E9%9D%A2%E6%9D%BF/"/>
    
    <category term="Vue" scheme="https://blog.imzjw.cn/tags/Vue/"/>
    
  </entry>
  
  <entry>
    <title>CentOS7 原生的方式安装 Redis 4</title>
    <link href="https://blog.imzjw.cn/posts/221bf322/"/>
    <id>https://blog.imzjw.cn/posts/221bf322/</id>
    <published>2021-03-23T09:15:16.000Z</published>
    <updated>2021-03-23T09:15:16.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="环境信息"><a href="#环境信息" class="headerlink" title="环境信息"></a>环境信息</h2><ul><li>CentOS 7.6</li></ul><h2 id="安装步骤"><a href="#安装步骤" class="headerlink" title="安装步骤"></a>安装步骤</h2><ol><li><p>首先安装 <code>gcc</code>，目地是编译软件</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install gcc-c++ </span><br></pre></td></tr></table></figure></li><li><p>通过 <code>wget</code> 命令下载 Redis-4.0.14，<a href="https://download.redis.io/releases/">其它版本</a></p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget http://download.redis.io/releases/redis-4.0.14.tar.gz</span><br></pre></td></tr></table></figure></li><li><p>解压</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tar -zxvf redis-4.0.14.tar.gz</span><br></pre></td></tr></table></figure></li><li><p>把解压的文件 <code>copy</code> 到 <code>/usr/local/src</code> 里面（纯属个人喜好）</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cp</span> -r redis-4.0.14 /usr/local/src/redis</span><br></pre></td></tr></table></figure></li><li><p>进入 <code>/usr/local/src/redis/deps</code> 进行编译依赖项</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /usr/local/src/redis/deps</span><br><span class="line">make hiredis lua jemalloc linenoise</span><br></pre></td></tr></table></figure></li><li><p>进入 <code>/usr/local/src/redis</code> 进行编译</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /usr/local/src/redis</span><br><span class="line">make</span><br></pre></td></tr></table></figure></li><li><p>把上面的 <code>redis</code> 目录安装到我们自己定义的目录（纯属个人喜好）</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> /usr/local/redis</span><br><span class="line">make install PREFIX=/usr/local/redis</span><br></pre></td></tr></table></figure></li><li><p>验证安装是否成功</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /usr/local/redis/bin</span><br><span class="line"><span class="built_in">ls</span></span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/221bf322/mark.2gcp5fy83xus.webp" alt="success"></p><p>看到如下启动文件就安装成功了！</p></li><li><p>现在就可以启动了</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 启动 redis server</span></span><br><span class="line">/usr/local/redis/bin/redis-server</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动 redis 客户端</span></span><br><span class="line">/usr/local/redis/bin/redis-cli</span><br></pre></td></tr></table></figure></li></ol><p>但是我不喜欢这样纸，我喜欢把配置文件复制一份到我自己自定义的目录里，然后再启动！</p><p>例如：</p><p>创建一个自定义目录，把配置文件到复制一份到自定义的目录，比如我的 <code>/root/myredis</code></p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> ~ &amp;&amp; <span class="built_in">mkdir</span> myredis</span><br><span class="line"><span class="built_in">cp</span> /usr/local/src/redis/redis.conf myredis</span><br></pre></td></tr></table></figure><p>最后以配置文件启动 <code>redis-server</code></p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/usr/local/redis/bin/redis-server /root/myredis/redis.conf</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/221bf322/run-redis.51cpdgfdhd.webp" alt="run-redis"></p><p>默认情况，Redis 不在后台运行的，我们修改配置文件让 Redis 在后台运行</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /root/myredis &amp;&amp; vim redis.conf</span><br></pre></td></tr></table></figure><p>然后 <code>/daemon</code> 找到 daemonize，按 <code>I</code> 进入插入模式，把 no 改为 yes，最后依次按下 <code>ESC</code> -&gt; <code>:WQ</code> 保存退出即可</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/221bf322/daemonize.4oah081wxfi.webp" alt="daemonize"></p><p>再次启动查看进程</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">/usr/local/redis/bin/redis-server /root/myredis/redis.conf</span><br><span class="line">ps -ef | grep redis</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/221bf322/process.5ywtp9doy4k0.webp" alt="process"></p><h2 id="客户端连接与退出"><a href="#客户端连接与退出" class="headerlink" title="客户端连接与退出"></a>客户端连接与退出</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">/usr/local/redis/bin/redis-cli</span><br><span class="line"><span class="comment"># 输入 ping，它会给你响应个 PONG</span></span><br><span class="line">127.0.0.1:6379&gt; ping</span><br><span class="line">PONG</span><br><span class="line"></span><br><span class="line"><span class="comment"># 退出客户端</span></span><br><span class="line">quit</span><br><span class="line"><span class="comment"># 或者 </span></span><br><span class="line"><span class="built_in">exit</span> </span><br><span class="line"><span class="comment"># 或者 </span></span><br><span class="line">CTRL + C</span><br></pre></td></tr></table></figure><p>停止 Redis</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">pkill redis-server</span><br><span class="line"><span class="comment"># 或者</span></span><br><span class="line">/usr/local/redis/bin/redis-cli shutdown</span><br><span class="line"></span><br><span class="line"><span class="comment"># 再次查看进程</span></span><br><span class="line">ps -ef | grep redis</span><br></pre></td></tr></table></figure><h2 id="bin-目录的文件说明"><a href="#bin-目录的文件说明" class="headerlink" title="bin 目录的文件说明"></a>bin 目录的文件说明</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">redis-benchmark  <span class="comment"># redis 性能测试工具</span></span><br><span class="line">redis-check-aof  <span class="comment"># 检查 aof 日志的工具</span></span><br><span class="line">redis-check-dump <span class="comment"># 检查 rdb 日志的工具</span></span><br><span class="line">redis-cli        <span class="comment"># 连接用的客户端</span></span><br><span class="line">redis-server     <span class="comment"># redis服务进程</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">环境信息 CentOS 7.6 安装步骤 1.首先安装 gcc，目地是编译软件 2.通过 wget 命令下载 Redis-4.0.14，其它版本 3.解压 4.把解压的文件 copy 到 /usr/local/src 里面（纯属个人喜好）</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Redis" scheme="https://blog.imzjw.cn/tags/Redis/"/>
    
  </entry>
  
  <entry>
    <title>另一种方式在 GitHub 上阅读源码</title>
    <link href="https://blog.imzjw.cn/posts/github1s/"/>
    <id>https://blog.imzjw.cn/posts/github1s/</id>
    <published>2021-03-19T12:30:48.000Z</published>
    <updated>2021-03-19T12:30:48.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>相信大家在 GitHub 上阅读源代码的时候，一个一个文件点啊点，结果还不是自己想要的，又得回退，很蛋疼，以至于去下载插件，比如 <a href="https://chrome.google.com/webstore/detail/octotree-github-code-tree/bkhaagjahfmjljalopjnoealnfndnagc">Octotree</a>，装上之后，仓库的左侧就会有个树形的菜单，如图</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/github1s/Octotree.is9lmvq9q28.webp" alt="Octotree"></p><p>但是只是多了个菜单，可能也无法满足某些人，<a href="https://jikipedia.com/definition/976651896">u1s1</a>，这插件确实挺好用的。</p><p>而本文讲的却是另一款工具，不是插件，也不是 <code>.exe</code>，而是 GitHub1s</p><p>项目地址：</p><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/conwnet/github1s"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=conwnet&repo=github1s&show_owner=true"/></a><h2 id="What-does-1s-mean"><a href="#What-does-1s-mean" class="headerlink" title="What does 1s mean?"></a><em>What does 1s mean?</em></h2><p>1s，大概就和项目描述所说的那样吧，1 秒钟阅读 GitHub 上的代码</p><h2 id="how-to-use"><a href="#how-to-use" class="headerlink" title="how to use?"></a><em>how to use?</em></h2><p>使用也挺简单</p><p>据项目的介绍说只需在 <code>github</code> 之后加个 <code>1s</code>，然后 <code>Enter</code> 即可阅读任何存储库</p><p>比如，我现在要阅读 <code>Spring Boot</code> 源码</p><p>地址是这个：<a href="https://github.com/spring-projects/spring-boot">https://github.com/spring-projects/spring-boot</a></p><p>打开之后很普通，没啥不同的</p><p>但是在 github 后加个 1s，你就会发现新大陆了</p><p><a href="https://github1s.com/spring-projects/spring-boot">https://github1s.com/spring-projects/spring-boot</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/github1s/github1s.5dhuo1svtb00.webp" alt="github1s"></p><p>oh! 天哪，这不是我们熟悉的 VS Code 吗</p><p>有了这玩意，在 GitHub 上看源码感觉就和在本地一样，体验极其爽！但注意是只读的，你不能编辑它。</p><p>而且，据说这个 GitHub1s 在大陆也能直接秒开！</p><p>还有就是，上图中的底部说明也说的很清楚了，GitHub1s 不是 GitHub 推出的，只是一个开源项目，不要说啥 GitHub 官方推出了新工具 - GitHub1s，那样人家会笑你的 <img no-lazy class="inline" src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/github1s/小丑.3t3fbnl4mkc0.webp" style="height:100px;"/> </p>]]></content>
    
    
    <summary type="html">相信大家在 GitHub 上阅读源代码的时候，一个一个文件点啊点，结果还不是自己想要的，又得回退，很蛋疼，以至于去下载插件，比如 Octotree，装上之后，仓库的左侧就会有个树形的菜单</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="GitHub" scheme="https://blog.imzjw.cn/tags/GitHub/"/>
    
  </entry>
  
  <entry>
    <title>Spring Boot + MyBatis 配置多数据源</title>
    <link href="https://blog.imzjw.cn/posts/a1bddb8c/"/>
    <id>https://blog.imzjw.cn/posts/a1bddb8c/</id>
    <published>2021-03-19T02:05:52.000Z</published>
    <updated>2021-03-19T02:05:52.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="创建数据库"><a href="#创建数据库" class="headerlink" title="创建数据库"></a>创建数据库</h2><p>新建俩数据库</p><table><thead><tr><th align="center">数据库</th><th align="center">表</th><th align="center">表字段</th></tr></thead><tbody><tr><td align="center">ds_master</td><td align="center">t_user</td><td align="center">uid、user_name、age</td></tr><tr><td align="center">ds_slave</td><td align="center">同上</td><td align="center">同上</td></tr></tbody></table><p>为了后面看出效果，表中插入的数据都不一样</p><p><code>ds_master</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/a1bddb8c/master.3b5eipo31jm0.webp" alt="ds_master"></p><p><code>ds_slave</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/a1bddb8c/slave.556irmkzdrg0.webp" alt="ds_slave"></p><h2 id="后台代码"><a href="#后台代码" class="headerlink" title="后台代码"></a>后台代码</h2><p>创建 <code>Spring Boot</code> 的工程，这里我的版本是 2.4.4，勾选 Lombok、Spring Web、MySQL Driver</p><p>完整 <code>pom.xml</code></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis.spring.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.1.3<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">scope</span>&gt;</span>runtime<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">optional</span>&gt;</span>true<span class="tag">&lt;/<span class="name">optional</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure><p>新建 <code>MasterDataSourceConfig</code> 类，作用就是配置我们主数据库相关的 bean</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="meta">@MapperScan(basePackages = &quot;cn.imzjw.mapper.master&quot;, sqlSessionFactoryRef = &quot;MasterSqlSessionFactory&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MasterDataSourceConfig</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 映射文件路径</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">MAPPER_LOCATION</span> <span class="operator">=</span> <span class="string">&quot;classpath:mapper/*Mapper.xml&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 表示这个数据源是默认的数据源</span></span><br><span class="line"><span class="comment">     * 必须要加 Primary 注解，如果两个数据源都没有 Primary 注解会报错</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean(name = &quot;MasterDataSource&quot;)</span></span><br><span class="line">    <span class="meta">@Primary</span></span><br><span class="line">    <span class="comment">// 配置文件前缀</span></span><br><span class="line">    <span class="meta">@ConfigurationProperties(prefix = &quot;spring.datasource.master&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> DataSource <span class="title function_">getPrimaryDateSource</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> DataSourceBuilder.create().build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean(name = &quot;MasterSqlSessionFactory&quot;)</span></span><br><span class="line">    <span class="meta">@Primary</span></span><br><span class="line">    <span class="keyword">public</span> SqlSessionFactory <span class="title function_">masterSqlSessionFactory</span><span class="params">(<span class="meta">@Qualifier(&quot;MasterDataSource&quot;)</span> DataSource datasource)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">SqlSessionFactoryBean</span> <span class="variable">bean</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SqlSessionFactoryBean</span>();</span><br><span class="line">        bean.setDataSource(datasource);</span><br><span class="line">        <span class="comment">// 配置映射文件</span></span><br><span class="line">        bean.setMapperLocations(<span class="keyword">new</span> <span class="title class_">PathMatchingResourcePatternResolver</span>().getResources(MAPPER_LOCATION));</span><br><span class="line">        <span class="comment">// 下划线转驼峰</span></span><br><span class="line">        bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(<span class="literal">true</span>);</span><br><span class="line">        <span class="keyword">return</span> bean.getObject();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean(&quot;MasterSqlSessionTemplate&quot;)</span></span><br><span class="line">    <span class="meta">@Primary</span></span><br><span class="line">    <span class="keyword">public</span> SqlSessionTemplate <span class="title function_">masterSqlSessionTemplate</span><span class="params">(<span class="meta">@Qualifier(&quot;MasterSqlSessionFactory&quot;)</span> SqlSessionFactory sessionfactory)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">SqlSessionTemplate</span>(sessionfactory);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>注解说明</p><ul><li>MapperScan：扫描 <code>mapper</code> 接口的</li><li>Primary：表示使用的是默认数据库</li><li>ConfigurationProperties：读取配置文件中的配置参数映射成一个对象，其中 <code>prefix</code> 表示参数的前缀</li></ul><p>新建 <code>SlaveDataSourceConfig</code> 类，配置第二个数据源</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="meta">@MapperScan(basePackages = &quot;cn.imzjw.mapper.slave&quot;, sqlSessionFactoryRef = &quot;SlaveSqlSessionFactory&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SlaveDataSourceConfig</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean(name = &quot;SlaveDataSource&quot;)</span></span><br><span class="line">    <span class="meta">@ConfigurationProperties(prefix = &quot;spring.datasource.slave&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> DataSource <span class="title function_">getSlaveDataSource</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> DataSourceBuilder.create().build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean(name = &quot;SlaveSqlSessionFactory&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> SqlSessionFactory <span class="title function_">slaveSqlSessionFactory</span><span class="params">(<span class="meta">@Qualifier(&quot;SlaveDataSource&quot;)</span> DataSource datasource)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">SqlSessionFactoryBean</span> <span class="variable">bean</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SqlSessionFactoryBean</span>();</span><br><span class="line">        bean.setDataSource(datasource);</span><br><span class="line">        <span class="comment">// 配置映射文件</span></span><br><span class="line">        bean.setMapperLocations(<span class="keyword">new</span> <span class="title class_">PathMatchingResourcePatternResolver</span>().getResources(MasterDataSourceConfig.MAPPER_LOCATION));</span><br><span class="line">        <span class="comment">// 下划线转驼峰</span></span><br><span class="line">        bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(<span class="literal">true</span>);</span><br><span class="line">        <span class="keyword">return</span> bean.getObject();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean(&quot;SlaveSqlSessionTemplate&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> SqlSessionTemplate <span class="title function_">slaveSqlSessionTemplate</span><span class="params">(<span class="meta">@Qualifier(&quot;SlaveSqlSessionFactory&quot;)</span> SqlSessionFactory sessionfactory)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">SqlSessionTemplate</span>(sessionfactory);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>新建 <code>User</code> 实体类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">User</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Integer uid;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">private</span> String userName;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>修改 <code>application.yaml</code></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="comment"># 默认数据库配置</span></span><br><span class="line">    <span class="attr">master:</span></span><br><span class="line">      <span class="attr">jdbc-url:</span> <span class="string">jdbc:mysql:///ds_master?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC&amp;useSSL=false</span></span><br><span class="line">      <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">    <span class="comment"># 次数据库配置</span></span><br><span class="line">    <span class="attr">slave:</span></span><br><span class="line">      <span class="attr">jdbc-url:</span> <span class="string">jdbc:mysql:///ds_slave?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC&amp;useSSL=false</span></span><br><span class="line">      <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br></pre></td></tr></table></figure><p>新建 <code>mapper</code> 接口和对应的 <code>xml</code> 文件</p><p><code>cn.imzjw.mapper.master.MasterUserMapper.java</code></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">MasterUserMapper</span> &#123;</span><br><span class="line"></span><br><span class="line">    List&lt;User&gt; <span class="title function_">findAll</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>cn.imzjw.mapper.slave.SlaveUserMapper.java</code></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">SlaveUserMapper</span> &#123;</span><br><span class="line"></span><br><span class="line">    List&lt;User&gt; <span class="title function_">findAll</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="note warning flat"><p>注： mapper 接口要在不同的包下 </p></div><p><code>MasterUserMapper.xml</code></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span> ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">mapper</span></span></span><br><span class="line"><span class="meta">        <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;cn.imzjw.mapper.master.MasterUserMapper&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;findAll&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;cn.imzjw.entity.User&quot;</span>&gt;</span></span><br><span class="line">        SELECT *</span><br><span class="line">        FROM t_user</span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure><p><code>SlaveUserMapper.xml</code></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span> ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">mapper</span></span></span><br><span class="line"><span class="meta">        <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;cn.imzjw.mapper.slave.SlaveUserMapper&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;findAll&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;cn.imzjw.entity.User&quot;</span>&gt;</span></span><br><span class="line">        SELECT *</span><br><span class="line">        FROM t_user</span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure><p>代码部分就已经完成了，现在新建个 <code>Controller</code> 测试测试</p><h2 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> MasterUserMapper masterUserMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> SlaveUserMapper slaveUserMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;master&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">primary</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> masterUserMapper.findAll();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;slave&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">secondary</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> slaveUserMapper.findAll();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>最后启动 Spring Boot 工程，分别访问 <code>http://localhost:8080/master</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/a1bddb8c/master_test.684qwdf36lc0.webp" alt="master_test"></p><p>和 <code>http://localhost:8080/slave</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/a1bddb8c/slave_test.40jjjwvmd3e0.webp" alt="slave_test"></p><p>到此，就已经完结了!!!</p><h2 id="踩过的坑"><a href="#踩过的坑" class="headerlink" title="踩过的坑"></a>踩过的坑</h2><p>实体类下划线转驼峰的问题，在多数据源中，尽管你在配置文件中配置了如下代码，也是没有效果的</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">mybatis:</span></span><br><span class="line">  <span class="attr">configuration:</span></span><br><span class="line">    <span class="attr">map-underscore-to-camel-case:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><p>解决办法就是在 <code>MasterDataSourceConfig</code> 里的工厂方法配置</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean(name = &quot;MasterSqlSessionFactory&quot;)</span></span><br><span class="line"><span class="meta">@Primary</span></span><br><span class="line"><span class="keyword">public</span> SqlSessionFactory <span class="title function_">masterSqlSessionFactory</span><span class="params">(<span class="meta">@Qualifier(&quot;MasterDataSource&quot;)</span> DataSource datasource)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">    <span class="type">SqlSessionFactoryBean</span> <span class="variable">bean</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SqlSessionFactoryBean</span>();</span><br><span class="line">    bean.setDataSource(datasource);</span><br><span class="line">    <span class="comment">// 配置映射文件</span></span><br><span class="line">    bean.setMapperLocations(<span class="keyword">new</span> <span class="title class_">PathMatchingResourcePatternResolver</span>().getResources(MAPPER_LOCATION));</span><br><span class="line">    <span class="comment">// 下划线转驼峰</span></span><br><span class="line">    bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(<span class="literal">true</span>);</span><br><span class="line">    <span class="keyword">return</span> bean.getObject();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>此外 <code>SlaveDataSourceConfig</code> 也要配置</p><p>第二个坑就是，配置映射文件必须要在下划线转驼峰之前，不然就会报错，以下就是个错误的例子</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 下划线转驼峰</span></span><br><span class="line">bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(<span class="literal">true</span>);</span><br><span class="line"><span class="comment">// 配置映射文件</span></span><br><span class="line">bean.setMapperLocations(<span class="keyword">new</span> <span class="title class_">PathMatchingResourcePatternResolver</span>().getResources(MAPPER_LOCATION));</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/a1bddb8c/error.dh8vhwi1z68.webp" alt="error"></p><p>所以必须要在它之前（正确的例子）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 配置映射文件</span></span><br><span class="line">bean.setMapperLocations(<span class="keyword">new</span> <span class="title class_">PathMatchingResourcePatternResolver</span>().getResources(MAPPER_LOCATION));</span><br><span class="line"><span class="comment">// 下划线转驼峰</span></span><br><span class="line">bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(<span class="literal">true</span>);</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">创建数据库，新建俩数据库，为了后面看出效果，表中插入的数据都不一样，创建 Spring Boot 的工程，这里我的版本是 2.4.4，勾选 踩过的坑</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="MyBatis" scheme="https://blog.imzjw.cn/tags/MyBatis/"/>
    
    <category term="Spring Boot" scheme="https://blog.imzjw.cn/tags/Spring-Boot/"/>
    
  </entry>
  
  <entry>
    <title>像专业人士一样使用 Google</title>
    <link href="https://blog.imzjw.cn/posts/aae542e3/"/>
    <id>https://blog.imzjw.cn/posts/aae542e3/</id>
    <published>2021-03-17T03:58:12.000Z</published>
    <updated>2021-03-17T03:58:12.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>今天在 Dev 社区看到的这篇帖子，虽然自己天天用 <code>Google</code>，但是这些技巧却不是那么的熟悉，所以分享给大家</p><p>原文：<a href="https://dev.to/denicmarko/google-like-a-pro-5cf6">Use Google like a pro</a></p><p>译：<a href="https://blog.imzjw.cn/">小嘉的部落格</a></p><p>谷歌搜索是每个开发人员最重要的技能之一。</p><p>让我告诉您如何更好地使用 Google。</p><p>开始吧！</p><h2 id="使用引号精确匹配搜索"><a href="#使用引号精确匹配搜索" class="headerlink" title="使用引号精确匹配搜索"></a>使用引号精确匹配搜索</h2><p>e.g <code>&quot;what is javascript&quot;</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/aae542e3/js.5a7w41oq0xk0.webp" alt="images"></p><h2 id="AND-运算符"><a href="#AND-运算符" class="headerlink" title="AND 运算符"></a>AND 运算符</h2><p>只会返回与他们都相关的结果</p><p>e.g <code>html AND css</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/aae542e3/AND.3n46lm4omns0.webp" alt="AND"></p><h2 id="OR-运算符"><a href="#OR-运算符" class="headerlink" title="OR 运算符"></a>OR 运算符</h2><p>获取与其中一个搜索词相关的结果</p><p>e.g <code>(javascript OR python) free course</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/aae542e3/OR.69n014ebaqc0.webp" alt="OR"></p><p>除此之外还有 <code>|</code> 也是和 <code>OR</code> 一样</p><h2 id="运算符"><a href="#运算符" class="headerlink" title="- 运算符"></a>- 运算符</h2><p>排除包含搜索词的结果</p><p>e.g <code>javascript -css</code></p><p>所以搜出来的结果都是与 <code>javascript</code> 相关</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/aae542e3/-.9lbuly10uhs.webp" alt="-"></p><h2 id="通配符"><a href="#通配符" class="headerlink" title="* 通配符"></a>* 通配符</h2><p>作为占位符，会被任何单词或短语替换。</p><p>e.g <code>&quot;how to start * in 6 months&quot;</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/aae542e3/_.6ee89s3z5g00.webp" alt="* 通配符"></p><h2 id="site"><a href="#site" class="headerlink" title="site:"></a>site:</h2><p>在单个网站内搜索，这样搜索出来都是与该网站相关的结果，一般想看自己的网站是否被搜索引擎收录了，都可以用 <code>site:</code></p><p>e.g <code>site:blog.imzjw.cn</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/aae542e3/imzjw.2c6u408781es.webp" alt="site"></p><p>还可以将搜索范围限制为域名后缀，例如 <code>site:com</code>、<code>site:cn</code>、<code>site:org</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/aae542e3/V1ncent.10ygm5ffq728.webp" alt="V1ncent"></p><h2 id="filetype"><a href="#filetype" class="headerlink" title="filetype"></a>filetype</h2><p>查找特定的文件类型。</p><p>e.g <code>filetype:pdf learn css</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/aae542e3/filetype.38e903ggguy0.webp" alt="filetype"></p><p>此外 <code>ext</code> 也是和 <code>filetype</code> 一样</p><p>e.g <code>Java ext:pdf</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/aae542e3/ext.4guvpoi22vi0.webp" alt="ext"></p><h2 id="搜索一系列的数字"><a href="#搜索一系列的数字" class="headerlink" title="搜索一系列的数字"></a>搜索一系列的数字</h2><p>e.g <code>ecmascript 2016..2018</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/aae542e3/ecmascript.2ty9f4dmatu0.webp" alt="images"></p>]]></content>
    
    
    <summary type="html">今天在 Dev 社区看到的这篇帖子，虽然自己天天用 Google，但是这些技巧却不是那么的熟悉，原文：Use Google like a pro，译：小嘉的部落格</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="Google" scheme="https://blog.imzjw.cn/tags/Google/"/>
    
  </entry>
  
  <entry>
    <title>Spring Boot 整合 Redis</title>
    <link href="https://blog.imzjw.cn/posts/boot-redis/"/>
    <id>https://blog.imzjw.cn/posts/boot-redis/</id>
    <published>2021-03-15T13:48:55.000Z</published>
    <updated>2021-03-15T13:48:55.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Redis 应该是目前使用最多的缓存，包括 Spring Boot 中我们也是会用 Redis 做很多事情，今天索性就来个整合教程，用 Spring Boot 那是相当的简单，只需要创建 Spring Boot 工程时，往那一勾，欸，就差不多了</p><h2 id="整合过程"><a href="#整合过程" class="headerlink" title="整合过程"></a>整合过程</h2><p><code>pom.xml</code>，Spring Boot 我用的是 <code>2.4.3</code> 版本</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-data-redis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>fastjson<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.2.74<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><p><code>application.yml</code></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># redis配置</span></span><br><span class="line">  <span class="attr">redis:</span></span><br><span class="line">    <span class="comment"># Redis 服务器地址</span></span><br><span class="line">    <span class="attr">host:</span> <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span></span><br><span class="line">    <span class="comment"># Redis 服务器端口</span></span><br><span class="line">    <span class="attr">port:</span> <span class="number">6379</span></span><br><span class="line">    <span class="comment"># Redis 服务器密码（默认为空）</span></span><br><span class="line">    <span class="attr">password:</span></span><br><span class="line">    <span class="attr">jedis:</span></span><br><span class="line">      <span class="attr">pool:</span></span><br><span class="line">        <span class="attr">max-active:</span> <span class="number">8</span></span><br><span class="line">        <span class="comment"># 连接池最大阻塞等待时间（使用负值表示没有限制）</span></span><br><span class="line">        <span class="attr">max-wait:</span> <span class="number">-1</span></span><br><span class="line">        <span class="comment"># 连接池中的最大空闲连接</span></span><br><span class="line">        <span class="attr">max-idle:</span> <span class="number">8</span></span><br><span class="line">        <span class="comment"># 连接池中的最小空闲连接</span></span><br><span class="line">        <span class="attr">min-idle:</span> <span class="number">0</span></span><br></pre></td></tr></table></figure><p><code>RedisUtils.java</code></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br><span class="line">501</span><br><span class="line">502</span><br><span class="line">503</span><br><span class="line">504</span><br><span class="line">505</span><br><span class="line">506</span><br><span class="line">507</span><br><span class="line">508</span><br><span class="line">509</span><br><span class="line">510</span><br><span class="line">511</span><br><span class="line">512</span><br><span class="line">513</span><br><span class="line">514</span><br><span class="line">515</span><br><span class="line">516</span><br><span class="line">517</span><br><span class="line">518</span><br><span class="line">519</span><br><span class="line">520</span><br><span class="line">521</span><br><span class="line">522</span><br><span class="line">523</span><br><span class="line">524</span><br><span class="line">525</span><br><span class="line">526</span><br><span class="line">527</span><br><span class="line">528</span><br><span class="line">529</span><br><span class="line">530</span><br><span class="line">531</span><br><span class="line">532</span><br><span class="line">533</span><br><span class="line">534</span><br><span class="line">535</span><br><span class="line">536</span><br><span class="line">537</span><br><span class="line">538</span><br><span class="line">539</span><br><span class="line">540</span><br><span class="line">541</span><br><span class="line">542</span><br><span class="line">543</span><br><span class="line">544</span><br><span class="line">545</span><br><span class="line">546</span><br><span class="line">547</span><br><span class="line">548</span><br><span class="line">549</span><br><span class="line">550</span><br><span class="line">551</span><br><span class="line">552</span><br><span class="line">553</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RedisUtils</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Resource</span></span><br><span class="line">    <span class="keyword">private</span> RedisTemplate&lt;String, Object&gt; redisTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> Set&lt;String&gt; <span class="title function_">keys</span><span class="params">(String keys)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> redisTemplate.keys(keys);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 指定缓存失效时间</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key  键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> time 时间(秒)</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">expire</span><span class="params">(String key, <span class="type">long</span> time)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (time &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                redisTemplate.expire(key, time, TimeUnit.SECONDS);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据 key 获取过期时间</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key 键 不能为null</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 时间(秒) 返回 0 代表为永久有效</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">long</span> <span class="title function_">getExpire</span><span class="params">(String key)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> redisTemplate.getExpire(key, TimeUnit.SECONDS);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 判断key是否存在</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key 键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> true 存在 false不存在</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">hasKey</span><span class="params">(String key)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> redisTemplate.hasKey(key);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 删除缓存</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key 可以传一个值或多个</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">del</span><span class="params">(String... key)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (key != <span class="literal">null</span> &amp;&amp; key.length &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (key.length == <span class="number">1</span>) &#123;</span><br><span class="line">                redisTemplate.delete(key[<span class="number">0</span>]);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                redisTemplate.delete((Collection&lt;String&gt;) CollectionUtils.arrayToList(key));</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 普通缓存获取</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key 键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 值</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">get</span><span class="params">(String key)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> key == <span class="literal">null</span> ? <span class="literal">null</span> : redisTemplate.opsForValue().get(key);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 普通缓存放入</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value 值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> true成功 false失败</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">set</span><span class="params">(String key, Object value)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            redisTemplate.opsForValue().set(key, value);</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 普通缓存放入并设置时间</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value 值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> time  时间(秒) time要大于0 如果time小于等于0 将设置无限期</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> true成功 false 失败</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">set</span><span class="params">(String key, Object value, <span class="type">long</span> time)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (time &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                set(key, value);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 递增</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> delta 要增加几(大于0)</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">long</span> <span class="title function_">incr</span><span class="params">(String key, <span class="type">long</span> delta)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (delta &lt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">&quot;递增因子必须大于0&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> redisTemplate.opsForValue().increment(key, delta);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 递减</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> delta 要减少几(小于0)</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">long</span> <span class="title function_">decr</span><span class="params">(String key, <span class="type">long</span> delta)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (delta &lt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">&quot;递减因子必须大于0&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> redisTemplate.opsForValue().increment(key, -delta);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * HashGet</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key  键 不能为null</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> item 项 不能为null</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 值</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">hget</span><span class="params">(String key, String item)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> redisTemplate.opsForHash().get(key, item);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取hashKey对应的所有键值</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key 键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 对应的多个键值</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> Map&lt;Object, Object&gt; <span class="title function_">hmget</span><span class="params">(String key)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> redisTemplate.opsForHash().entries(key);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * HashSet</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key 键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> map 对应多个键值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> true 成功 false 失败</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">hmset</span><span class="params">(String key, Map&lt;String, Object&gt; map)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            redisTemplate.opsForHash().putAll(key, map);</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * HashSet 并设置时间</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key  键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> map  对应多个键值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> time 时间(秒)</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> true成功 false失败</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">hmset</span><span class="params">(String key, Map&lt;String, Object&gt; map, <span class="type">long</span> time)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            redisTemplate.opsForHash().putAll(key, map);</span><br><span class="line">            <span class="keyword">if</span> (time &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                expire(key, time);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 向一张hash表中放入数据,如果不存在将创建</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> item  项</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value 值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> true 成功 false失败</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">hset</span><span class="params">(String key, String item, Object value)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            redisTemplate.opsForHash().put(key, item, value);</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 向一张hash表中放入数据,如果不存在将创建</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> item  项</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value 值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> true 成功 false失败</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">hset</span><span class="params">(String key, String item, Object value, <span class="type">long</span> time)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            redisTemplate.opsForHash().put(key, item, value);</span><br><span class="line">            <span class="keyword">if</span> (time &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                expire(key, time);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 删除hash表中的值</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key  键 不能为null</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> item 项 可以使多个 不能为null</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">hdel</span><span class="params">(String key, Object... item)</span> &#123;</span><br><span class="line">        redisTemplate.opsForHash().delete(key, item);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 判断hash表中是否有该项的值</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key  键 不能为null</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> item 项 不能为null</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> true 存在 false不存在</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">hHasKey</span><span class="params">(String key, String item)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> redisTemplate.opsForHash().hasKey(key, item);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * hash递增 如果不存在,就会创建一个 并把新增后的值返回</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key  键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> item 项</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> by   要增加几(大于0)</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">double</span> <span class="title function_">hincr</span><span class="params">(String key, String item, <span class="type">double</span> by)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> redisTemplate.opsForHash().increment(key, item, by);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * hash递减</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key  键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> item 项</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> by   要减少记(小于0)</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">double</span> <span class="title function_">hdecr</span><span class="params">(String key, String item, <span class="type">double</span> by)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> redisTemplate.opsForHash().increment(key, item, -by);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据key获取Set中的所有值</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key 键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> Set&lt;Object&gt; <span class="title function_">sGet</span><span class="params">(String key)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> redisTemplate.opsForSet().members(key);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据value从一个set中查询,是否存在</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value 值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> true 存在 false不存在</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">sHasKey</span><span class="params">(String key, Object value)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> redisTemplate.opsForSet().isMember(key, value);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 将数据放入set缓存</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key    键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> values 值 可以是多个</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 成功个数</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">long</span> <span class="title function_">sSet</span><span class="params">(String key, Object... values)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> redisTemplate.opsForSet().add(key, values);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 将set数据放入缓存</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key    键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> time   时间(秒)</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> values 值 可以是多个</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 成功个数</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">long</span> <span class="title function_">sSetAndTime</span><span class="params">(String key, <span class="type">long</span> time, Object... values)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">Long</span> <span class="variable">count</span> <span class="operator">=</span> redisTemplate.opsForSet().add(key, values);</span><br><span class="line">            <span class="keyword">if</span> (time &gt; <span class="number">0</span>)</span><br><span class="line">                expire(key, time);</span><br><span class="line">            <span class="keyword">return</span> count;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取set缓存的长度</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key 键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">long</span> <span class="title function_">sGetSetSize</span><span class="params">(String key)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> redisTemplate.opsForSet().size(key);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 移除值为value的</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key    键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> values 值 可以是多个</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 移除的个数</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">long</span> <span class="title function_">setRemove</span><span class="params">(String key, Object... values)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">Long</span> <span class="variable">count</span> <span class="operator">=</span> redisTemplate.opsForSet().remove(key, values);</span><br><span class="line">            <span class="keyword">return</span> count;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// ===============================list=================================</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取list缓存的内容</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> start 开始</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> end   结束 0 到 -1代表所有值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> List&lt;Object&gt; <span class="title function_">lGet</span><span class="params">(String key, <span class="type">long</span> start, <span class="type">long</span> end)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> redisTemplate.opsForList().range(key, start, end);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取list缓存的长度</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key 键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">long</span> <span class="title function_">lGetListSize</span><span class="params">(String key)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> redisTemplate.opsForList().size(key);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 通过索引 获取list中的值</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> index 索引 index&gt;=0时， 0 表头，1 第二个元素，依次类推；index&lt;0时，-1，表尾，-2倒数第二个元素，依次类推</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">lGetIndex</span><span class="params">(String key, <span class="type">long</span> index)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> redisTemplate.opsForList().index(key, index);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 将list放入缓存</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value 值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">lSet</span><span class="params">(String key, Object value)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            redisTemplate.opsForList().rightPush(key, value);</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 将list放入缓存</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value 值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> time  时间(秒)</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">lSet</span><span class="params">(String key, Object value, <span class="type">long</span> time)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            redisTemplate.opsForList().rightPush(key, value);</span><br><span class="line">            <span class="keyword">if</span> (time &gt; <span class="number">0</span>)</span><br><span class="line">                expire(key, time);</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 将list放入缓存</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value 值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">lSet</span><span class="params">(String key, List&lt;Object&gt; value)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            redisTemplate.opsForList().rightPushAll(key, value);</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 将list放入缓存</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value 值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> time  时间(秒)</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">lSet</span><span class="params">(String key, List&lt;Object&gt; value, <span class="type">long</span> time)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            redisTemplate.opsForList().rightPushAll(key, value);</span><br><span class="line">            <span class="keyword">if</span> (time &gt; <span class="number">0</span>)</span><br><span class="line">                expire(key, time);</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据索引修改list中的某条数据</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> index 索引</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value 值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">lUpdateIndex</span><span class="params">(String key, <span class="type">long</span> index, Object value)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            redisTemplate.opsForList().set(key, index, value);</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 移除N个值为value</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> key   键</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> count 移除多少个</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> value 值</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 移除的个数</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">long</span> <span class="title function_">lRemove</span><span class="params">(String key, <span class="type">long</span> count, Object value)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">Long</span> <span class="variable">remove</span> <span class="operator">=</span> redisTemplate.opsForList().remove(key, count, value);</span><br><span class="line">            <span class="keyword">return</span> remove;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这个 <code>redis</code> 工具类网上也有很多，我这个也是复制网上的，为什么选择这个呢，因为这个注释我看的真的是很舒服 ^_^</p><p><code>RedisConfig.java</code></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="meta">@ConditionalOnClass(RedisOperations.class)</span></span><br><span class="line"><span class="meta">@EnableConfigurationProperties(RedisProperties.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RedisConfig</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="meta">@ConditionalOnMissingBean(name = &quot;redisTemplate&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> RedisTemplate&lt;Object, Object&gt; <span class="title function_">redisTemplate</span><span class="params">(</span></span><br><span class="line"><span class="params">        RedisConnectionFactory redisConnectionFactory)</span> &#123;</span><br><span class="line">        RedisTemplate&lt;Object, Object&gt; template = <span class="keyword">new</span> <span class="title class_">RedisTemplate</span>&lt;&gt;();</span><br><span class="line">        <span class="comment">// 使用 fastjson 序列化</span></span><br><span class="line">        <span class="type">FastJsonRedisSerializer</span> <span class="variable">fastJsonRedisSerializer</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FastJsonRedisSerializer</span>(Object.class);</span><br><span class="line">        <span class="comment">// value 值的序列化采用 fastJsonRedisSerializer</span></span><br><span class="line">        template.setValueSerializer(fastJsonRedisSerializer);</span><br><span class="line">        template.setHashValueSerializer(fastJsonRedisSerializer);</span><br><span class="line">        <span class="comment">// key 的序列化采用 StringRedisSerializer</span></span><br><span class="line">        template.setKeySerializer(<span class="keyword">new</span> <span class="title class_">StringRedisSerializer</span>());</span><br><span class="line">        template.setHashKeySerializer(<span class="keyword">new</span> <span class="title class_">StringRedisSerializer</span>());</span><br><span class="line">        template.setConnectionFactory(redisConnectionFactory);</span><br><span class="line">        <span class="keyword">return</span> template;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="meta">@ConditionalOnMissingBean(StringRedisTemplate.class)</span></span><br><span class="line">    <span class="keyword">public</span> StringRedisTemplate <span class="title function_">stringRedisTemplate</span><span class="params">(</span></span><br><span class="line"><span class="params">        RedisConnectionFactory redisConnectionFactory)</span> &#123;</span><br><span class="line">        <span class="type">StringRedisTemplate</span> <span class="variable">template</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StringRedisTemplate</span>();</span><br><span class="line">        template.setConnectionFactory(redisConnectionFactory);</span><br><span class="line">        <span class="keyword">return</span> template;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>接下来就开始测试一下</p><p><code>TestRedisController.java</code></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestRedisController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> RedisUtils redisUtils;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;setKey&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">setKey</span><span class="params">(String k, String v)</span> &#123;</span><br><span class="line">        redisUtils.set(k, v);</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;success&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;getKey&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">getKey</span><span class="params">(String k)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> redisUtils.get(k);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>启动 Spring Boot 程序</p><p>访问 <code>http://localhost:8080/setKey?k=小嘉的部落格&amp;v=https://blog.imzjw.cn</code></p><p>参数：</p><ul><li><code>k</code>：键</li><li><code>v</code>：值</li></ul><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/boot-redis/k.pdkc5vxkq9c.webp" alt="images"></p><p>访问 <code>http://localhost:8080/getKey?k=小嘉的部落格</code> 通过键获取值</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/boot-redis/v.1i5p9cinihq8.webp" alt="images"></p><p>整合就结束了!!!</p><a class="btn-beautify purple" href="https://github.com/zjwo/springboot_redis"   title="源码下载"><i class="far fa-hand-point-right"></i><span>源码下载</span></a>]]></content>
    
    
    <summary type="html">Redis 应该是目前使用最多的缓存，包括 Spring Boot 中我们也是会用 Redis 做很多事情，今天索性就来个整合教程，用 Spring Boot 那是相当的简单，只需要创建 Spring Boot 工程时</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Redis" scheme="https://blog.imzjw.cn/tags/Redis/"/>
    
    <category term="Spring Boot" scheme="https://blog.imzjw.cn/tags/Spring-Boot/"/>
    
  </entry>
  
  <entry>
    <title>使用阿里巴巴出品的 Druid 实现 MySQL 连接加密</title>
    <link href="https://blog.imzjw.cn/posts/1b5df44b/"/>
    <id>https://blog.imzjw.cn/posts/1b5df44b/</id>
    <published>2021-03-10T10:10:35.000Z</published>
    <updated>2021-03-10T10:10:35.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>我们在开发的时候，都会把源代码上传到代码托管平台，例如：GitHub，Gitlab 等，但是这样有一个问题，会存在泄露的风险，而数据库连接信息作为源码的一部分，一旦泄露，后果不堪设想</p><p>为了避免这个问题，我们<code>至少</code>要对数据库的密码进行加密</p><p>所以我们就使用阿里巴巴提供的 Druid 来进行加密</p><h2 id="What-is-Druid"><a href="#What-is-Druid" class="headerlink" title="What is Druid"></a><em>What is Druid</em></h2><p>Druid（中文译为德鲁伊） 是阿里开源的连接池，是 Java 语言中最好的数据库连接池，Druid 能够提供强大的监控和扩展功能，是为监控而生的数据库连接池！</p><p>GitHub 地址：</p><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/alibaba/druid"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=alibaba&repo=druid&show_owner=true"/></a><h2 id="使用-Druid-加密"><a href="#使用-Druid-加密" class="headerlink" title="使用 Druid 加密"></a>使用 <em>Druid</em> 加密</h2><p>运行环境</p><ul><li>Spring Boot 2.4.3</li><li>MySQL 5.7</li><li>Java 1.8</li><li>Maven 3.6.3</li><li>IntelliJ IDEA 2020.3.2</li></ul><p>这里我直接用上上篇的 <a href="https://blog.imzjw.cn/posts/boot-mybatis/">Spring Boot 整合 MyBatis</a> 的案例进行演示</p><p>首先添加 Druid 依赖</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>druid-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.2.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="生成密文"><a href="#生成密文" class="headerlink" title="生成密文"></a>生成密文</h3><p>使用 Druid 提供的 <code>ConfigTools</code> 类来加密，代码如下</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">    ConfigTools.main(<span class="keyword">new</span> <span class="title class_">String</span>[]&#123;<span class="string">&quot;此处写你的数据库密码&quot;</span>&#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>执行结果如下</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">privateKey:MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAtjXeooEqq5GFiBsFe/pvJ7CUdea0D2lZQwroX+9iGvqA+eODkXlxAvWJpLJvb556e+bvE4PTSKOnqG1WGYbExwIDAQABAkBXQYTUHTbp4k4n14jQziTcxNrFbqUk5TfXE3KZ1sEo5/dYSAaKKrH1RvCv1Qq1BAiEA/Iwg1Iv3/+/wageQysq3donzE3InTOlMjyWmljPS75MCIQC4s5MKdTPgpCgLCPrrTCoIwWbGCCRux6Cjt32/KvNOfQIgWdRCDTgoI1omKqC8SNWoQjq5Qm51Oi81sykSQxT1748CIFbUDIb5DBdJ9I0jfpoI5yXQjZkBEOeHLyxnwVSSQ2kdAiBJGgYiTzuCAr0IVndmXHD1ExmPBlPeNqnZGQT56joMeQ==</span><br><span class="line">publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALY13qKBKquRhYgbBXAsdq13KNASD9pWUMK6F/vYhr6gPnjg5F5cQL1iaSyb2+eenvm7xOD00ijp6htVhmGxMcCAwEAAQ==</span><br><span class="line">password:Jriab0IWm8Ibx88A91oFk5VP8crpLnU96fy+jAjb4MKOSAD6ZPezPYL6QZMIAlGEym6oXBzedKS/AZOKcEH+Iw==</span><br></pre></td></tr></table></figure><ul><li>privateKey：私钥，暂时用不到，用于密码的加密</li><li>publicKey：公钥，用于密码的解密</li><li>password：加密以后的密码</li></ul><div class="note danger flat"><p>要实现数据库的加密，主要使用 publicKey（公钥）和 password（密文），这样就把明文转换成密文了。</p></div><p>配置 <code>application.yaml</code></p><p>原始的数据库配置还记得吗？</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1b5df44b/1.2ajutzya9ydc.webp" alt="images"></p><p>而使用 Druid 进行加密之后</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># 配置数据库</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">    <span class="attr">type:</span> <span class="string">com.alibaba.druid.pool.DruidDataSource</span></span><br><span class="line">    <span class="attr">druid:</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">jdbc:mysql:///mybatis?serverTimezone=Asia/Shanghai&amp;characterEncoding=UTF-8&amp;useSSL=false</span></span><br><span class="line">      <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">password:</span> <span class="string">Jriab0IWm8Ibx88A91oFk5VP8crpLnU96fy+jAjb4MKOSAD6ZPezPYL6QZMIAlGEym6oXBzedKS/AZOKcEH+Iw==</span></span><br><span class="line">      <span class="attr">filters:</span> <span class="string">config</span></span><br><span class="line">      <span class="attr">connect-properties:</span></span><br><span class="line">        <span class="attr">config.decrypt:</span> <span class="literal">true</span></span><br><span class="line">        <span class="attr">config.decrypt.key:</span> <span class="string">MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALY13qKBKquRhYgbBXAsdq13KNASD9pWUMK6F/vYhr6gPnjg5F5cQL1iaSyb2+eenvm7xOD00ijp6htVhmGxMcCAwEAAQ==</span></span><br></pre></td></tr></table></figure><p><code>password</code> 对应上一步用 <code>ConfigTools</code> 类生成的 <code>password</code>，<code>config.decrypt.key</code> 对应 <code>publicKey</code></p><p>如此如此，启动项目，可以发现能正常访问</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1b5df44b/list.6sqvc103kzg0.webp" alt="start"></p><p>但是你们有没有发现到一个问题，就是公钥和密文都写在配置文件里了，万一有人拿到公钥和密文，那不就可以解密了…</p><h3 id="解决思路"><a href="#解决思路" class="headerlink" title="解决思路"></a>解决思路</h3><p>我们可以在启动项目的时候将公钥动态的设置到项目中，说白了就是设置环境的参数，如此密码就有保障了</p><p>再次修改 <code>application.yaml</code></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># 配置数据库</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">    <span class="attr">type:</span> <span class="string">com.alibaba.druid.pool.DruidDataSource</span></span><br><span class="line">    <span class="attr">druid:</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">jdbc:mysql:///mybatis?serverTimezone=Asia/Shanghai&amp;characterEncoding=UTF-8&amp;useSSL=false</span></span><br><span class="line">      <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">password:</span> <span class="string">Jriab0IWm8Ibx88A91oFk5VP8crpLnU96fy+jAjb4MKOSAD6ZPezPYL6QZMIAlGEym6oXBzedKS/AZOKcEH+Iw==</span></span><br><span class="line">      <span class="comment"># encrypt config</span></span><br><span class="line">      <span class="attr">filters:</span> <span class="string">config</span></span><br><span class="line">      <span class="attr">connect-properties:</span></span><br><span class="line">        <span class="attr">config.decrypt:</span> <span class="literal">true</span></span><br><span class="line">        <span class="attr">config.decrypt.key:</span> <span class="string">$&#123;druid.publickey&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="attr">mybatis:</span></span><br><span class="line">  <span class="attr">type-aliases-package:</span> <span class="string">cn.imzjw.entity</span></span><br><span class="line">  <span class="attr">mapper-locations:</span> <span class="string">classpath:mapper/*.xml</span></span><br></pre></td></tr></table></figure><p>公钥修改成 <code>$&#123;druid.publickey&#125;</code></p><p><code>druid.publickey</code> 是自定义的，并不是固定的写法</p><p>最后设置环境参数</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1b5df44b/222.516ttehvkx8.webp" alt="images"></p><p>以上都是在开发的时候操作的，如果是生产环境中，可以参考如下命令：</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -jar xxx.jar --druid.publickey=公钥</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1b5df44b/qwasd.3uqwboxb1mi0.webp" alt="images"></p><h2 id="解密操作"><a href="#解密操作" class="headerlink" title="解密操作"></a>解密操作</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">publickey</span> <span class="operator">=</span> <span class="string">&quot;公钥&quot;</span>;</span><br><span class="line">    <span class="type">String</span> <span class="variable">password</span> <span class="operator">=</span> <span class="string">&quot;密文&quot;</span>;</span><br><span class="line">    LOGGER.info(ConfigTools.decrypt(publickey, password));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">我们在开发的时候，都会把源代码上传到代码托管平台，例如：GitHub，GitLab 等，但是这样有一个问题，会存在泄露的风险，而数据库连接信息作为源码的一部分，一旦泄露，后果不堪设想</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="MySQL" scheme="https://blog.imzjw.cn/tags/MySQL/"/>
    
  </entry>
  
  <entry>
    <title>关于 IntelliJ IDEA 2020 版本不自动导入 Maven 依赖问题</title>
    <link href="https://blog.imzjw.cn/posts/2820aac4/"/>
    <id>https://blog.imzjw.cn/posts/2820aac4/</id>
    <published>2021-03-09T05:52:06.000Z</published>
    <updated>2021-03-09T05:52:06.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在练习项目的时候，缺少了依赖，然后我就跑去 Maven 仓库寻找依赖，复制粘贴到 <code>pom.xml</code> 时，结果还是报错，提示没有这个类，最后在 Maven 工具栏看到没有自动导入进来…IDEA 坏了？谷歌查了下，原来这是因为 IntelliJ IDEA 从 2020 版本开始，为了防止 <code>pom</code> 更新和 <code>Maven</code> 自动导包时卡 “死” 的问题，所以就取消了自动导包的机制，但是也新增了导入按钮和快捷键。</p><h2 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h2><h3 id="第一种（按钮）"><a href="#第一种（按钮）" class="headerlink" title="第一种（按钮）"></a>第一种（按钮）</h3><p>当我们修改了 Maven 依赖时，<code>pom</code> 文件右上角就会出现一个 maven 的小图标，点一下就可以导入依赖了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/2820aac4/211.5qyhp98qv2s0.webp" alt="images"></p><div class="note warning flat"><p>注：默认情况下是不会出现的，只有当删除了依赖，或者添加依赖时，才会出现</p></div><h3 id="第二种（快捷键）"><a href="#第二种（快捷键）" class="headerlink" title="第二种（快捷键）"></a>第二种（快捷键）</h3><p><span class="inline-tag red">Mac</span> ：<kbd>Command</kbd> + <kbd>SHIFT</kbd> + <kbd>O</kbd></p><p><span class="inline-tag blue">Windows</span> ：<kbd>CTRL</kbd> + <kbd>SHIFT</kbd> + <kbd>O</kbd></p><span class='p red'>But</span> 这是 IDEA 默认的快捷键，我相信绝大部分人，会修改快捷键为 Eclipse，比如我<p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/2820aac4/xxx.36r66h715h40.webp" alt="keymap"></p><p>所以 <kbd>CTRL</kbd> + <kbd>SHIFT</kbd> + <kbd>O</kbd> 就会没效果啦，不过不要紧，我们可以设置快捷键</p><p>打开 <code>File | Settings | Keymap</code>，搜索 <code>load changes</code>，然后右键选择 <code>Add Keyboard Shortcut</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/2820aac4/xxx.4gyti1nf8vm0.webp" alt="images"></p><p>进行设置快捷键</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/2820aac4/image-20210309142801262.1y5ps19bfm3k.webp" alt="images"></p><div class="note danger flat"><p>如果出现黄色的警告，这是因为快捷键已经分配给其它的选项了</p></div><p>最后就可以用你设置的快捷键进行导入依赖啦！</p>]]></content>
    
    
    <summary type="html">在练习项目的时候，缺少了依赖，然后我就跑去 Maven 仓库寻找依赖，复制粘贴到 pom.xml 时，结果还是报错，提示没有这个类，最后在 Maven 工具栏看到没有自动导入进来</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="IntelliJ IDEA" scheme="https://blog.imzjw.cn/tags/IntelliJ-IDEA/"/>
    
  </entry>
  
  <entry>
    <title>Spring Boot 整合 MyBatis</title>
    <link href="https://blog.imzjw.cn/posts/boot-mybatis/"/>
    <id>https://blog.imzjw.cn/posts/boot-mybatis/</id>
    <published>2021-03-08T12:27:16.000Z</published>
    <updated>2021-03-08T12:27:16.000Z</updated>
    
    <content type="html"><![CDATA[<p>Spring Boot 整合 MyBatis 是非常简单的，相比 Spring 整合减少了非常多的配置，几步就整合完成了</p><h2 id="所涉及的环境"><a href="#所涉及的环境" class="headerlink" title="所涉及的环境"></a>所涉及的环境</h2><ul><li>Intellij IDEA 2020.3.2</li><li>Spring Boot 2.3.1</li><li>JDK 1.8</li><li>Maven 3.6.3</li><li>MySQL 5.7</li></ul><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><p>创建 Spring Boot 工程就不再阐述了</p><p>创建表结构</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> IF <span class="keyword">EXISTS</span> `<span class="keyword">user</span>`;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> `<span class="keyword">user</span>` (</span><br><span class="line">  `id` <span class="type">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="keyword">NULL</span> AUTO_INCREMENT,</span><br><span class="line">  `username` <span class="type">varchar</span>(<span class="number">10</span>) <span class="keyword">COLLATE</span> utf8mb4_unicode_ci <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line">  `password` <span class="type">varchar</span>(<span class="number">10</span>) <span class="keyword">COLLATE</span> utf8mb4_unicode_ci <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line">  <span class="keyword">PRIMARY</span> KEY (`id`)</span><br><span class="line">) ENGINE<span class="operator">=</span>InnoDB AUTO_INCREMENT<span class="operator">=</span><span class="number">79</span> <span class="keyword">DEFAULT</span> CHARSET<span class="operator">=</span>utf8mb4 <span class="keyword">COLLATE</span><span class="operator">=</span>utf8mb4_unicode_ci;</span><br></pre></td></tr></table></figure><p>添加 Maven 依赖（pom.xml）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis.spring.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.1.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">scope</span>&gt;</span>runtime<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">optional</span>&gt;</span>true<span class="tag">&lt;/<span class="name">optional</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure><p>编写实体类（<code>cn.imzjw.entity.User.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span><span class="comment">// &lt;- Lombok 插件，idea 2020 默认是装了，如未装，请删掉手动生成 setter、getter，或安装 Lombok</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">User</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String username;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String password;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">serialVersionUID</span> <span class="operator">=</span> <span class="number">1L</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编写持久层（<code>cn.imzjw.mapper.UserMapper.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">UserMapper</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询所有 by garvey</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 结果</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    List&lt;User&gt; <span class="title function_">selectAll</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编写业务层（<code>cn.imzjw.service.UserService.java</code>）……</p><p>业务层实现类（<code>cn.imzjw.service.impl.UserServiceImpl.java</code>）……</p><p>这里就不贴出业务层的代码了，因为和持久层接口代码是一样的，项目也没什么业务逻辑，只是一个整合</p><p>下面就编写 <code>mapper</code> 映射文件（<code>resources/mapper/UserMapper.xml</code>）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">mapper</span> <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span> <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;cn.imzjw.mapper.UserMapper&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">&quot;BaseResultMap&quot;</span> <span class="attr">type</span>=<span class="string">&quot;User&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">id</span> <span class="attr">column</span>=<span class="string">&quot;id&quot;</span> <span class="attr">property</span>=<span class="string">&quot;id&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;username&quot;</span> <span class="attr">property</span>=<span class="string">&quot;username&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;password&quot;</span> <span class="attr">property</span>=<span class="string">&quot;password&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">sql</span> <span class="attr">id</span>=<span class="string">&quot;Base_Column_List&quot;</span>&gt;</span></span><br><span class="line">        id, username, `password`</span><br><span class="line">    <span class="tag">&lt;/<span class="name">sql</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;selectAll&quot;</span> <span class="attr">resultMap</span>=<span class="string">&quot;BaseResultMap&quot;</span>&gt;</span></span><br><span class="line">        SELECT</span><br><span class="line">        <span class="tag">&lt;<span class="name">include</span> <span class="attr">refid</span>=<span class="string">&quot;Base_Column_List&quot;</span>/&gt;</span></span><br><span class="line">        FROM `user`</span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure><p>编写 <code>application.yml</code></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># 数据库配置</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">jdbc:mysql:///mybatis?useUnicode=true&amp;characterEncoding=utf-8</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">    <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line"></span><br><span class="line"><span class="attr">mybatis:</span></span><br><span class="line">  <span class="attr">type-aliases-package:</span> <span class="string">cn.imzjw.entity</span>     <span class="comment"># 开启别名</span></span><br><span class="line">  <span class="attr">mapper-locations:</span> <span class="string">classpath:mapper/*.xml</span>  <span class="comment"># 映射文件路径</span></span><br></pre></td></tr></table></figure><p>编写 <code>Controller</code> （<code>cn.imzjw.controller.UserController.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> UserService userService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;list&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> List&lt;User&gt; <span class="title function_">findAll</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> userService.selectAll();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>最后在主程序扫描 <code>Mapper</code> 层接口</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="meta">@MapperScan(&quot;cn.imzjw.mapper&quot;)</span> <span class="comment">// 扫描 Mapper 层接口</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SpringbootMybatisApplication</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        SpringApplication.run(SpringbootMybatisApplication.class, args);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编写完成！</p><p>项目结构</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/boot-mybatis/jiegou.4ta3rc3reyo0.webp" alt="jiegou"></p><p>启动项目访问 <code>localhost:8080/list</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/boot-mybatis/list.6sqvc103kzg0.webp" alt="list"></p><p>整合结束!!!</p>]]></content>
    
    
    <summary type="html">Spring Boot 整合 MyBatis 是非常简单的，相比 SSM 减少了非常多的配置，几步就整合完成了，所涉及的环境 Intellij IDEA 2020.3.2，Spring Boot 2.3.1</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="MyBatis" scheme="https://blog.imzjw.cn/tags/MyBatis/"/>
    
    <category term="Spring Boot" scheme="https://blog.imzjw.cn/tags/Spring-Boot/"/>
    
  </entry>
  
  <entry>
    <title>MyBatis - 动态 SQL</title>
    <link href="https://blog.imzjw.cn/posts/c0de53b8/"/>
    <id>https://blog.imzjw.cn/posts/c0de53b8/</id>
    <published>2021-03-06T12:45:22.000Z</published>
    <updated>2021-03-06T12:45:22.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>动态 SQL 是 MyBatis 的强大特性之一，如果你使用过 JDBC 或其它类似的框架，你应该能理解根据不同条件拼接 SQL 语句有多痛苦，例如拼接时要确保不能忘记添加必要的空格，还要注意去掉列表最后一个列名的逗号。</p><p>如果使用动态 SQL，就可以彻底摆脱这种痛苦。</p><h2 id="if"><a href="#if" class="headerlink" title="if"></a>if</h2><p><code>if</code> 就是简单的条件判断，利用 <code>if</code> 语句我们可以实现某些简单的条件选择。</p><p>我们先来看一下持久层方法</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">List&lt;User&gt; <span class="title function_">selectByNameAndPwd</span><span class="params">(User user)</span>;</span><br></pre></td></tr></table></figure><p><code>Mapper.xml</code> 映射文件</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;selectByName&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;User&quot;</span>&gt;</span></span><br><span class="line">    SELECT *</span><br><span class="line">    FROM user</span><br><span class="line">    <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;username != null and username != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">        WHERE username LIKE #&#123;username&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;password != null and password != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">        AND password LIKE #&#123;password&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure><div class="note success flat"><p>使用 if 标签来做了条件判断，这样可以根据用户填入的参数来动态加入查询条件。</p></div><p>测试类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">    <span class="type">InputStream</span> <span class="variable">is</span> <span class="operator">=</span> Resources.getResourceAsStream(<span class="string">&quot;mybatis-config.xml&quot;</span>);</span><br><span class="line">    <span class="type">SqlSessionFactory</span> <span class="variable">sqlSessionFactory</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SqlSessionFactoryBuilder</span>().build(is);</span><br><span class="line">    <span class="type">SqlSession</span> <span class="variable">sqlSession</span> <span class="operator">=</span> sqlSessionFactory.openSession();</span><br><span class="line">    <span class="comment">// getMapper(); 会通过动态代理动态的生成 UserMapper 的代理实现类</span></span><br><span class="line">    <span class="type">UserMapper</span> <span class="variable">userMapper</span> <span class="operator">=</span> sqlSession.getMapper(UserMapper.class);</span><br><span class="line"></span><br><span class="line">    userMapper.selectByNameAndPwd(<span class="keyword">new</span> <span class="title class_">User</span>(<span class="literal">null</span>, <span class="string">&quot;%a%&quot;</span>, <span class="literal">null</span>)).forEach(s -&gt; System.out.println(s));</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 关闭连接</span></span><br><span class="line">    sqlSession.close();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>控制台 SQL 语句输出结果：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">02</span>:<span class="number">23</span>,<span class="number">638</span> ==&gt;  Preparing: select * from user where username LIKE ?  (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">02</span>:<span class="number">23</span>,<span class="number">673</span> ==&gt; Parameters: %a%(String) (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">02</span>:<span class="number">23</span>,<span class="number">695</span> &lt;==      Total: <span class="number">1</span> (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">[User(id=<span class="number">1</span>, username=admin, password=admin123)]</span><br><span class="line"></span><br><span class="line">Process finished with exit code <span class="number">0</span></span><br></pre></td></tr></table></figure><p>password 为 <code>null</code>，所以最后的 SQL 语句并没有拼接 password 条件</p><h2 id="choose"><a href="#choose" class="headerlink" title="choose"></a>choose</h2><p>choose 元素的作用就相当于 JAVA 中的 switch 语句，通常都是与 when 和 otherwise 搭配的</p><p>持久层方法</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">List&lt;User&gt; <span class="title function_">selectByNameAndPwd2</span><span class="params">(User user)</span>;</span><br></pre></td></tr></table></figure><p><code>Mapper.xml</code> 映射文件</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;selectByNameAndPwd2&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;User&quot;</span>&gt;</span></span><br><span class="line">    SELECT *</span><br><span class="line">    FROM user</span><br><span class="line">    <span class="tag">&lt;<span class="name">where</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">choose</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">when</span> <span class="attr">test</span>=<span class="string">&quot;username != null and username != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">                AND username LIKE #&#123;username&#125;</span><br><span class="line">            <span class="tag">&lt;/<span class="name">when</span>&gt;</span></span><br><span class="line"></span><br><span class="line">            <span class="tag">&lt;<span class="name">when</span> <span class="attr">test</span>=<span class="string">&quot;password != null and password != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">                AND password LIKE #&#123;password&#125;</span><br><span class="line">            <span class="tag">&lt;/<span class="name">when</span>&gt;</span></span><br><span class="line"></span><br><span class="line">            <span class="tag">&lt;<span class="name">otherwise</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">otherwise</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">choose</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">where</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure><p>测试类</p><p>这里我吧 <code>username</code> 置为 <code>null</code> 了</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">    <span class="type">InputStream</span> <span class="variable">is</span> <span class="operator">=</span> Resources.getResourceAsStream(<span class="string">&quot;mybatis-config.xml&quot;</span>);</span><br><span class="line">    <span class="type">SqlSessionFactory</span> <span class="variable">sqlSessionFactory</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SqlSessionFactoryBuilder</span>().build(is);</span><br><span class="line">    <span class="type">SqlSession</span> <span class="variable">sqlSession</span> <span class="operator">=</span> sqlSessionFactory.openSession();</span><br><span class="line">    <span class="comment">// getMapper(); 会通过动态代理动态的生成 UserMapper 的代理实现类</span></span><br><span class="line">    <span class="type">UserMapper</span> <span class="variable">userMapper</span> <span class="operator">=</span> sqlSession.getMapper(UserMapper.class);</span><br><span class="line">    </span><br><span class="line">    userMapper.selectByNameAndPwd2(<span class="keyword">new</span> <span class="title class_">User</span>(<span class="literal">null</span>, <span class="literal">null</span>, <span class="string">&quot;%123%&quot;</span>)).forEach(s -&gt; System.out.println(s));</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 关闭连接</span></span><br><span class="line">    sqlSession.close();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>控制台 SQL 语句输出结果：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">14</span>:<span class="number">20</span>,<span class="number">477</span> ==&gt;  Preparing: SELECT * FROM user WHERE password LIKE ?  (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">14</span>:<span class="number">20</span>,<span class="number">519</span> ==&gt; Parameters: %root%(String) (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">14</span>:<span class="number">20</span>,<span class="number">542</span> &lt;==      Total: <span class="number">1</span> (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">[User(id=<span class="number">2</span>, username=root, password=root123)]</span><br></pre></td></tr></table></figure><p>如果 username 不为空，则拼接 username 的条件。如果 password 不为空，则拼接 password 的条件。但是 <code>otherwise</code> 的条件可以为空</p><h2 id="where"><a href="#where" class="headerlink" title="where"></a>where</h2><p><code>where</code> 语句的作用主要是简化 SQL 语句中 where 中的条件判断的。MyBatis 会智能的帮你处理这些情况，如果所有的条件都不满足那么 MyBatis 就会查出所有的记录，如果输出后是 AND 开头的，MyBatis 会把第一个 AND 忽略，当然如果是 <code>OR</code> 开头的，MyBatis 也会把它忽略，此外，在 where 元素中你不需要考虑空格的问题，MyBatis 会智能的帮你加上，简直不要太爽！</p><p>持久层方法</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">List&lt;User&gt; <span class="title function_">selectByNameAndPwd3</span><span class="params">(User user)</span>;</span><br></pre></td></tr></table></figure><p><code>Mapper.xml</code> 映射文件</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;selectByNameAndPwd3&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;User&quot;</span>&gt;</span></span><br><span class="line">    SELECT *</span><br><span class="line">    FROM user</span><br><span class="line">    <span class="tag">&lt;<span class="name">where</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;username != null and username != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">            AND username LIKE #&#123;username&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;password != null and password != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">            AND password LIKE #&#123;password&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">where</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure><p>测试类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">    <span class="type">InputStream</span> <span class="variable">is</span> <span class="operator">=</span> Resources.getResourceAsStream(<span class="string">&quot;mybatis-config.xml&quot;</span>);</span><br><span class="line">    <span class="type">SqlSessionFactory</span> <span class="variable">sqlSessionFactory</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SqlSessionFactoryBuilder</span>().build(is);</span><br><span class="line">    <span class="type">SqlSession</span> <span class="variable">sqlSession</span> <span class="operator">=</span> sqlSessionFactory.openSession();</span><br><span class="line">    <span class="comment">// getMapper(); 会通过动态代理动态的生成 UserMapper 的代理实现类</span></span><br><span class="line">    <span class="type">UserMapper</span> <span class="variable">userMapper</span> <span class="operator">=</span> sqlSession.getMapper(UserMapper.class);</span><br><span class="line"></span><br><span class="line">    userMapper.selectByNameAndPwd3(<span class="keyword">new</span> <span class="title class_">User</span>(<span class="literal">null</span>, <span class="string">&quot;%a%&quot;</span>, <span class="literal">null</span>)).forEach(s -&gt; System.out.println(s));</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 关闭连接</span></span><br><span class="line">    sqlSession.close();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>控制台 SQL 语句输出结果：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">20</span>:<span class="number">47</span>,<span class="number">610</span> ==&gt;  Preparing: select * from user WHERE username LIKE ?  (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">20</span>:<span class="number">47</span>,<span class="number">648</span> ==&gt; Parameters: %a%(String) (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">20</span>:<span class="number">47</span>,<span class="number">671</span> &lt;==      Total: <span class="number">1</span> (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">User(id=<span class="number">1</span>, username=admin, password=admin123)</span><br></pre></td></tr></table></figure><p>可以看到，<code>username</code> 前面的 <code>AND</code> 关键字被自动删掉了</p><h2 id="sql"><a href="#sql" class="headerlink" title="sql"></a>sql</h2><p>MyBatis 中 <code>sql</code> 标签定义 SQL 片段，<code>include</code> 标签引用，可以复用 SQL 片段。</p><p>持久层方法</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">List&lt;User&gt; <span class="title function_">selectByNameAndPwd4</span><span class="params">(User user)</span>;</span><br></pre></td></tr></table></figure><p><code>Mapper.xml</code> 映射文件</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">sql</span> <span class="attr">id</span>=<span class="string">&quot;userField&quot;</span>&gt;</span></span><br><span class="line">    SELECT id, username, password</span><br><span class="line">    FROM user</span><br><span class="line"><span class="tag">&lt;/<span class="name">sql</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;selectByNameAndPwd4&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;User&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">include</span> <span class="attr">refid</span>=<span class="string">&quot;userField&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">where</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;username != null and username != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">            AND username LIKE #&#123;username&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;password != null and password != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">            AND password LIKE #&#123;password&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">where</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure><p>我们把反复使用的 <code>SELECT</code> 语句使用 <code>sql</code> 标签抽取出来，然后使用 <code>include</code> 标签引用，这样配置的复用性大大地提高啦</p><p>测试类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">    <span class="type">InputStream</span> <span class="variable">is</span> <span class="operator">=</span> Resources.getResourceAsStream(<span class="string">&quot;mybatis-config.xml&quot;</span>);</span><br><span class="line">    <span class="type">SqlSessionFactory</span> <span class="variable">sqlSessionFactory</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SqlSessionFactoryBuilder</span>().build(is);</span><br><span class="line">    <span class="type">SqlSession</span> <span class="variable">sqlSession</span> <span class="operator">=</span> sqlSessionFactory.openSession();</span><br><span class="line">    <span class="comment">// getMapper(); 会通过动态代理动态的生成 UserMapper 的代理实现类</span></span><br><span class="line">    <span class="type">UserMapper</span> <span class="variable">userMapper</span> <span class="operator">=</span> sqlSession.getMapper(UserMapper.class);</span><br><span class="line"></span><br><span class="line">    userMapper.selectByNameAndPwd4(<span class="keyword">new</span> <span class="title class_">User</span>(<span class="literal">null</span>, <span class="string">&quot;%a%&quot;</span>, <span class="literal">null</span>)).forEach(s -&gt; System.out.println(s));</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 关闭连接</span></span><br><span class="line">    sqlSession.close();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>控制台 SQL 语句输出结果：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">28</span>:<span class="number">04</span>,<span class="number">592</span> ==&gt;  Preparing: select id, username, password from user WHERE username LIKE ?  (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">28</span>:<span class="number">04</span>,<span class="number">629</span> ==&gt; Parameters: %a%(String) (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">28</span>:<span class="number">04</span>,<span class="number">649</span> &lt;==      Total: <span class="number">1</span> (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">User(id=<span class="number">1</span>, username=admin, password=admin123)</span><br></pre></td></tr></table></figure><h2 id="foreach"><a href="#foreach" class="headerlink" title="foreach"></a>foreach</h2><p><code>foreach</code> 的主要用在构建 <code>in</code> 条件中，它可以在 SQL 语句中进行迭代一个集合。<code>foreach</code> 元素的属性主要有</p><table><thead><tr><th align="center">属性名</th><th align="center">说明</th></tr></thead><tbody><tr><td align="center">item</td><td align="center">集合中每一个元素进行迭代时的别名</td></tr><tr><td align="center">index</td><td align="center">指定一个名字，用于表示在迭代过程中，每次迭代到的位置</td></tr><tr><td align="center">collection</td><td align="center">该属性是必须指定的，该值存在 3 种情况：1. 如果传入的是单参数且参数类型是一个 List 的时候，collection 属性值就为 list。2. 如果传入的是单参数且参数类型是一个 <code>array</code> 数组的时候，collection 的属性值就为 <code>array</code>。 3. 如果传入的参数是多个的时候，我们就需要把它们封装成一个 Map 了，当然单参数也可以封装成 Map，实际上如果你在传入参数的时候，在 MyBatis 里面也是会把它封装成一个 Map 的，Map 的 key 就是参数名，所以这个时候 collection 属性值就是传入的 List 或 array 对象在自己封装的 Map 里面的 key</td></tr><tr><td align="center">open</td><td align="center">表示该语句以什么开始</td></tr><tr><td align="center">separator</td><td align="center">表示在每次进行迭代之间以什么符号作为分隔符</td></tr><tr><td align="center">close</td><td align="center">表示以什么结束</td></tr></tbody></table><p>持久层方法</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> <span class="title function_">deleteUser</span><span class="params">(List&lt;Integer&gt; ids)</span>;</span><br></pre></td></tr></table></figure><p><code>Mapper.xml</code> 映射文件</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">delete</span> <span class="attr">id</span>=<span class="string">&quot;deleteUser&quot;</span> <span class="attr">parameterType</span>=<span class="string">&quot;integer&quot;</span>&gt;</span></span><br><span class="line">    DELETE</span><br><span class="line">    FROM user WHERE</span><br><span class="line">    <span class="tag">&lt;<span class="name">foreach</span> <span class="attr">collection</span>=<span class="string">&quot;list&quot;</span> <span class="attr">item</span>=<span class="string">&quot;id&quot;</span> <span class="attr">open</span>=<span class="string">&quot;id IN(&quot;</span> <span class="attr">close</span>=<span class="string">&quot;)&quot;</span> <span class="attr">separator</span>=<span class="string">&quot;,&quot;</span>&gt;</span></span><br><span class="line">        #&#123;id&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">foreach</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">delete</span>&gt;</span></span><br></pre></td></tr></table></figure><p>这里传入的参数是 <code>List</code> 类型，所以 collection 属性为 <code>list</code></p><p>测试类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">    <span class="type">InputStream</span> <span class="variable">is</span> <span class="operator">=</span> Resources.getResourceAsStream(<span class="string">&quot;mybatis-config.xml&quot;</span>);</span><br><span class="line">    <span class="type">SqlSessionFactory</span> <span class="variable">sqlSessionFactory</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SqlSessionFactoryBuilder</span>().build(is);</span><br><span class="line">    <span class="type">SqlSession</span> <span class="variable">sqlSession</span> <span class="operator">=</span> sqlSessionFactory.openSession();</span><br><span class="line">    <span class="comment">// getMapper(); 会通过动态代理动态的生成 UserMapper 的代理实现类</span></span><br><span class="line">    <span class="type">UserMapper</span> <span class="variable">userMapper</span> <span class="operator">=</span> sqlSession.getMapper(UserMapper.class);</span><br><span class="line">    </span><br><span class="line">    ArrayList&lt;Integer&gt; ids = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">    ids.add(<span class="number">2</span>);</span><br><span class="line">    ids.add(<span class="number">3</span>);</span><br><span class="line">    ids.add(<span class="number">4</span>);</span><br><span class="line">    ids.add(<span class="number">5</span>);</span><br><span class="line">    ids.add(<span class="number">6</span>);</span><br><span class="line">    userMapper.deleteUser(ids);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 提交事务</span></span><br><span class="line">    sqlSession.commit();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 关闭连接</span></span><br><span class="line">    sqlSession.close();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>控制台 SQL 语句输出结果：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">44</span>:<span class="number">39</span>,<span class="number">149</span> ==&gt;  Preparing: DELETE FROM user WHERE id <span class="title function_">IN</span><span class="params">( ? , ? , ? , ? , ? )</span>  (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">44</span>:<span class="number">39</span>,<span class="number">190</span> ==&gt; Parameters: <span class="number">2</span>(Integer), <span class="number">3</span>(Integer), <span class="number">4</span>(Integer), <span class="number">5</span>(Integer), <span class="number">6</span>(Integer) (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">44</span>:<span class="number">39</span>,<span class="number">196</span> &lt;==    Updates: <span class="number">5</span> (BaseJdbcLogger.java:<span class="number">159</span>)</span><br></pre></td></tr></table></figure><h2 id="set"><a href="#set" class="headerlink" title="set"></a>set</h2><p>既有 <code>set</code> 关键字的作用，还可以自动去掉 <code>&lt;set&gt;</code> 标签拼接后的字符串最后一个 <code>,</code> 号</p><p><code>set</code> 元素可以用于动态包含需要更新的列，忽略其它不更新的列</p><p>持久层方法</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> <span class="title function_">updateUser</span><span class="params">(User user)</span>;</span><br></pre></td></tr></table></figure><p><code>Mapper.xml</code> 映射文件</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">update</span> <span class="attr">id</span>=<span class="string">&quot;updateUser&quot;</span>&gt;</span></span><br><span class="line">    UPDATE user</span><br><span class="line">    <span class="tag">&lt;<span class="name">set</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;username != null and username != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">            username = #&#123;username&#125;,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;password != null and password != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">            password = #&#123;password&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">set</span>&gt;</span></span><br><span class="line">    WHERE id = #&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">update</span>&gt;</span></span><br></pre></td></tr></table></figure><p><code>set</code> 元素会动态地在行首插入 <code>SET</code> 关键字，并会删掉额外的逗号，比如 <code>WHERE</code> 前面的 <code>,</code> 号，不然就会导致 SQL 语句失败</p><p>测试类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">    <span class="type">InputStream</span> <span class="variable">is</span> <span class="operator">=</span> Resources.getResourceAsStream(<span class="string">&quot;mybatis-config.xml&quot;</span>);</span><br><span class="line">    <span class="type">SqlSessionFactory</span> <span class="variable">sqlSessionFactory</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SqlSessionFactoryBuilder</span>().build(is);</span><br><span class="line">    <span class="type">SqlSession</span> <span class="variable">sqlSession</span> <span class="operator">=</span> sqlSessionFactory.openSession();</span><br><span class="line">    <span class="comment">// getMapper(); 会通过动态代理动态的生成 UserMapper 的代理实现类</span></span><br><span class="line">    <span class="type">UserMapper</span> <span class="variable">userMapper</span> <span class="operator">=</span> sqlSession.getMapper(UserMapper.class); </span><br><span class="line"></span><br><span class="line">    <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">User</span>();</span><br><span class="line">    user.setUsername(<span class="string">&quot;garvey&quot;</span>);</span><br><span class="line">    user.setPassword(<span class="string">&quot;123456&quot;</span>);</span><br><span class="line">    user.setId(<span class="number">7</span>);</span><br><span class="line">    userMapper.updateUser(user);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 提交事务</span></span><br><span class="line">    sqlSession.commit();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 关闭连接</span></span><br><span class="line">    sqlSession.close();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>控制台 SQL 语句输出结果：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">57</span>:<span class="number">50</span>,<span class="number">262</span> ==&gt;  Preparing: UPDATE user <span class="type">SET</span> <span class="variable">password</span> <span class="operator">=</span> ? <span class="type">WHERE</span> <span class="variable">id</span> <span class="operator">=</span> ?  (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">57</span>:<span class="number">50</span>,<span class="number">295</span> ==&gt; Parameters: <span class="number">123456</span>(String), <span class="number">9</span>(Integer) (BaseJdbcLogger.java:<span class="number">159</span>)</span><br><span class="line">DEBUG <span class="number">03</span>-<span class="number">06</span> <span class="number">21</span>:<span class="number">57</span>:<span class="number">50</span>,<span class="number">300</span> &lt;==    Updates: <span class="number">1</span> (BaseJdbcLogger.java:<span class="number">159</span>)</span><br></pre></td></tr></table></figure><p>另外也可以使用 <code>trim</code> 标签</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">update</span> <span class="attr">id</span>=<span class="string">&quot;updateUser2&quot;</span>&gt;</span></span><br><span class="line">    UPDATE user</span><br><span class="line">    <span class="tag">&lt;<span class="name">trim</span> <span class="attr">prefix</span>=<span class="string">&quot;set&quot;</span> <span class="attr">suffixOverrides</span>=<span class="string">&quot;,&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;username != null and username != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">            username = #&#123;username&#125;,</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;password != null and password != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">            password = #&#123;password&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">trim</span>&gt;</span></span><br><span class="line">    WHERE id = #&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">update</span>&gt;</span></span><br></pre></td></tr></table></figure><p>更多动态 SQL 参考 <a href="https://mybatis.org/mybatis-3/zh/dynamic-sql.html">MyBatis 3 - 动态 SQL</a></p>]]></content>
    
    
    <summary type="html">动态 SQL 是 MyBatis 的强大特性之一，如果你使用过 JDBC 或其它类似的框架，你应该能理解根据不同条件拼接 SQL 语句有多痛苦，例如拼接时要确保不能忘记添加必要的空格</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="MyBatis" scheme="https://blog.imzjw.cn/tags/MyBatis/"/>
    
  </entry>
  
  <entry>
    <title>MyBatis 的别名配置与使用</title>
    <link href="https://blog.imzjw.cn/posts/23a8e497/"/>
    <id>https://blog.imzjw.cn/posts/23a8e497/</id>
    <published>2021-03-05T13:44:50.000Z</published>
    <updated>2021-03-05T13:44:50.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在 <code>MyBatis</code> 的配置文件中开启别名的话，这样我们在 <code>mapper.xml</code> 文件中的 <code>parameterType</code> 和 <code>resultType</code> 中就可以使用别名了。其实这是为了避免在 <code>xml</code> 文件中输入过长的全限定类名而简化实体名的编写。</p><p><code>MyBatis</code> 本身也自定义了一些别名，我们可以在 <code>mapper.xml</code> 文件中直接使用这些别名</p><table><thead><tr><th align="center">别名</th><th align="center">映射的类型</th></tr></thead><tbody><tr><td align="center">_byte</td><td align="center">byte</td></tr><tr><td align="center">_long</td><td align="center">long</td></tr><tr><td align="center">_short</td><td align="center">short</td></tr><tr><td align="center">_int</td><td align="center">int</td></tr><tr><td align="center">_integer</td><td align="center">int</td></tr><tr><td align="center">_double</td><td align="center">double</td></tr><tr><td align="center">_float</td><td align="center">float</td></tr><tr><td align="center">_boolean</td><td align="center">boolean</td></tr><tr><td align="center">string</td><td align="center">String</td></tr><tr><td align="center">byte</td><td align="center">Byte</td></tr><tr><td align="center">long</td><td align="center">Long</td></tr><tr><td align="center">short</td><td align="center">Short</td></tr><tr><td align="center">int</td><td align="center">Integer</td></tr><tr><td align="center">integer</td><td align="center">Integer</td></tr><tr><td align="center">double</td><td align="center">Double</td></tr><tr><td align="center">float</td><td align="center">Float</td></tr><tr><td align="center">boolean</td><td align="center">Boolean</td></tr><tr><td align="center">date</td><td align="center">Date</td></tr><tr><td align="center">decimal</td><td align="center">BigDecimal</td></tr><tr><td align="center">bigdecimal</td><td align="center">BigDecimal</td></tr><tr><td align="center">map</td><td align="center">Map</td></tr></tbody></table><h2 id="MyBatis-自定义别名"><a href="#MyBatis-自定义别名" class="headerlink" title="MyBatis 自定义别名"></a>MyBatis 自定义别名</h2><p>可以在 <code>mybatis</code> 的配置文件中开启别名</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span> ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">configuration</span></span></span><br><span class="line"><span class="meta">        <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Config 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-config.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--开启别名--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">typeAliases</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">type</span>=<span class="string">&quot;cn.imzjw.entity.Book&quot;</span> <span class="attr">alias</span>=<span class="string">&quot;book&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">type</span>=<span class="string">&quot;cn.imzjw.entity.User&quot;</span> <span class="attr">alias</span>=<span class="string">&quot;user&quot;</span>/&gt;</span></span><br><span class="line">        ...</span><br><span class="line">        ... 订单</span><br><span class="line">    <span class="tag">&lt;/<span class="name">typeAliases</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 数据库连接信息--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">environments</span> <span class="attr">default</span>=<span class="string">&quot;mysql&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">environment</span> <span class="attr">id</span>=<span class="string">&quot;mysql&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">transactionManager</span> <span class="attr">type</span>=<span class="string">&quot;jdbc&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">transactionManager</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">dataSource</span> <span class="attr">type</span>=<span class="string">&quot;pooled&quot;</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;url&quot;</span> <span class="attr">value</span>=<span class="string">&quot;jdbc:mysql:///book?characterEcndoing=utf8&quot;</span>/&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driver&quot;</span> <span class="attr">value</span>=<span class="string">&quot;com.mysql.jdbc.Driver&quot;</span>/&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span> <span class="attr">value</span>=<span class="string">&quot;root&quot;</span>/&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;root&quot;</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">dataSource</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">environment</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">environments</span>&gt;</span></span><br></pre></td></tr></table></figure><p>这种方式的缺点就是要一个个的给所有实体类开启别名</p><p><strong>方式二：</strong></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span> ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">configuration</span></span></span><br><span class="line"><span class="meta">        <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Config 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-config.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--开启别名--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">typeAliases</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">type</span>=<span class="string">&quot;cn.imzjw.entity&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">typeAliases</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 数据库连接信息--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">environments</span> <span class="attr">default</span>=<span class="string">&quot;mysql&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">environment</span> <span class="attr">id</span>=<span class="string">&quot;mysql&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">transactionManager</span> <span class="attr">type</span>=<span class="string">&quot;jdbc&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">transactionManager</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">dataSource</span> <span class="attr">type</span>=<span class="string">&quot;pooled&quot;</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;url&quot;</span> <span class="attr">value</span>=<span class="string">&quot;jdbc:mysql:///book?characterEcndoing=utf8&quot;</span>/&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driver&quot;</span> <span class="attr">value</span>=<span class="string">&quot;com.mysql.jdbc.Driver&quot;</span>/&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span> <span class="attr">value</span>=<span class="string">&quot;root&quot;</span>/&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;root&quot;</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">dataSource</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">environment</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">environments</span>&gt;</span></span><br></pre></td></tr></table></figure><p>直接扫描实体类包下的所有实体类，简单粗暴，用这种方式的，别名亦是类名，首字母大写小写都可以</p><h2 id="如何使用别名？"><a href="#如何使用别名？" class="headerlink" title="如何使用别名？"></a>如何使用别名？</h2><p>在 <code>xxxMapper.xml</code> 文件使用别名</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">insert</span> <span class="attr">id</span>=<span class="string">&quot;addBook&quot;</span> <span class="attr">parameterType</span>=<span class="string">&quot;Book&quot;</span>&gt;</span></span><br><span class="line">    INSERT INTO book (book_name, book_counts, detail) VALUES (#&#123;bookName&#125;, #&#123;bookCounts&#125;, #&#123;detail&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">insert</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;selectAllBook&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;book&quot;</span>&gt;</span></span><br><span class="line">    SELECT * FROM book</span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure><p>原本这里的 <code>parameterType</code> 和 <code>resultType</code> 都是要写全限定类名，然而我们开启了别名之后，直接就写别名，简便了许多！</p>]]></content>
    
    
    <summary type="html">在 MyBatis 的配置文件中开启别名的话，这样我们在 mapper.xml 文件中的 parameterType 和 resultType 中就可以使用别名了。其实这是为了避免在 xml 文件中输入过长的全限定类名而简化实体名的编写。</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="MyBatis" scheme="https://blog.imzjw.cn/tags/MyBatis/"/>
    
  </entry>
  
  <entry>
    <title>记一次对 IntelliJ IDEA 的所有设置</title>
    <link href="https://blog.imzjw.cn/posts/7891a5c7/"/>
    <id>https://blog.imzjw.cn/posts/7891a5c7/</id>
    <published>2021-03-01T07:58:23.000Z</published>
    <updated>2021-03-01T07:58:23.000Z</updated>
    
    <content type="html"><![CDATA[<p>对 IDEA 进行设置，让开发的时候更加便利顺手</p><p>以下是我对 IDEA 的设置，可供参考</p><p>IDEA 版本 2020.3.2</p><h2 id="主题设置"><a href="#主题设置" class="headerlink" title="主题设置"></a>主题设置</h2><p>自带了四种主题</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/image-20210301160452587.684bhdyzzbk.webp" alt="img"></p><p>黑暗：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/cpddo/p_img@e111d325c8b12bee41f091ff1d0fa4d494987300/2021/03/01/8336c3598e97bca321abdab330e57a74.webp" alt="img"></p><p>明亮：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/cpddo/p_img@e944596cc07523d54696acbb619044e44044e07f/2021/03/01/531cf5b1a3b1665ef145d8b0a9c21247.webp" alt="img"></p><p>Windows 10 明亮效果：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/cpddo/p_img@d132e8b9765744552fe53718f314722a5d564249/2021/03/01/8e27b9ac037ec397a67c886305be966c.webp" alt="img"></p><p>对比度，一般都没人用吧</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/cpddo/p_img@7d318728f9ebc8006c641044dfb08d8ab9c4f1dc/2021/03/01/0c8d4a3c16321723ff05227a6daad954.webp" alt="img"></p><h2 id="字体大小设置"><a href="#字体大小设置" class="headerlink" title="字体大小设置"></a>字体大小设置</h2><p><code>IDE font</code> 是针对 IDE 工具的，<code>Editor font</code> 是代码窗口的也就是代码的字体大小</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/20240503/blogimage.4jnwsz3z0k.png" alt="blogimage"></p><p>还有一种控制台字体设置</p><p>​    <img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/cpddo/p_img@f50fe26a66181bc4df936c966e62dcb8dd0df481/2021/03/01/dda2f6c8abd21d4c622eff6b2b55d664.webp" alt="img"></p><h2 id="编码格式设置"><a href="#编码格式设置" class="headerlink" title="编码格式设置"></a>编码格式设置</h2><p>在 <code>File -&gt; Settings -&gt; Editor -&gt; File Encodings</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/01d38d50f7b9c6e682f327cb057944f4.webp" alt="img"></p><h2 id="自动导包设置"><a href="#自动导包设置" class="headerlink" title="自动导包设置"></a>自动导包设置</h2><p>在 <code>File -&gt; Settings -&gt; Editor -&gt; General -&gt; Auto Import</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/img.4imvrqnflwy0.webp" alt="img"></p><p><code>Insert imports on paste</code></p><ul><li>Always：有需要导入的包名时，会自动导入，不会弹提示框</li><li>ASK：有需要导入的包名时，会弹提示框，问你要不要导入</li><li>None：有需要导入的包名时，不会弹提示框，也不会自动导入。</li></ul><p><code>Add unambiguous imports on the fly</code>：这个就是自动导入功能了，当你输入类名后，声明就被自动导入了。</p><p><code>Optimize imports on fly</code>：把不用的声明移除掉。</p><h2 id="自动忽略大小写设置"><a href="#自动忽略大小写设置" class="headerlink" title="自动忽略大小写设置"></a>自动忽略大小写设置</h2><p>在 <code>File -&gt; Settings -&gt; Editor -&gt; General -&gt; Code Completion</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/xxx.bk4hppw727s.webp" alt="img"></p><h2 id="关闭-IDEA-自动更新设置"><a href="#关闭-IDEA-自动更新设置" class="headerlink" title="关闭 IDEA 自动更新设置"></a>关闭 IDEA 自动更新设置</h2><p>在 <code>File | Settings | Appearance &amp; Behavior | System Settings | Updates</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/xxx.44lyizv9zyu0.webp" alt="img"></p><h2 id="方法之间的分割线"><a href="#方法之间的分割线" class="headerlink" title="方法之间的分割线"></a>方法之间的分割线</h2><p>在 <code>File -&gt; Settings -&gt; Editor -&gt; General -&gt; Appearance</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/img.1gvf8xrcsmo0.webp" alt="img"></p><p>效果：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/img.1bmki7edq8qo.webp" alt="img"></p><h2 id="注释设置"><a href="#注释设置" class="headerlink" title="注释设置"></a>注释设置</h2><p>使用 IDEA 快捷键注释默认是这样的</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/image-20210301163402274.1fqutvw02xds.webp" alt="img"></p><p>本人非常不喜欢，我喜欢在它旁边空一行的注释</p><p>在 <code>File -&gt; Settings -&gt; Editor -&gt; Code Style -&gt; Java</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/image-20210301163617653.4j98f29617u0.webp" alt="img"></p><p>效果：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/image-20210301163702088.5m7k3f0ym3w0.webp" alt="image-20210301163702088"></p><p>现在我看着就很舒服</p><p><code>HTML</code> 、<code>XML</code> 注释也是一样，把那俩勾勾去掉即可</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/image-20210301163827282.4jvvp7o1tbc0.webp" alt="img"></p><h2 id="代码自动编译"><a href="#代码自动编译" class="headerlink" title="代码自动编译"></a>代码自动编译</h2><p>在 <code>File -&gt; Settings -&gt; Build,Execution,Deployment -&gt; Compiler</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/image-20210301163947602.ifkc0cexeeg.webp" alt="image-20210301163947602"></p><p>设置 Lombok 编译</p><p>在 <code>File | Settings | Build, Execution, Deployment | Compiler | Annotation Processors</code></p><p>勾上 <code>Enable annotation processing</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/image-20210301164151544.2lrnnxi4vqg0.webp" alt="image-20210301164151544"></p><h2 id="Maven-设置"><a href="#Maven-设置" class="headerlink" title="Maven 设置"></a>Maven 设置</h2><p>在 <code>File | Settings | Build, Execution, Deployment | Build Tools | Maven</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/image-20210301165247469.6b5ufig1ul00.webp" alt="image-20210301165247469"></p><h2 id="IDEA-查看内存使用情况"><a href="#IDEA-查看内存使用情况" class="headerlink" title="IDEA 查看内存使用情况"></a>IDEA 查看内存使用情况</h2><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/image-20210301165614422.1b9ys7imfv28.webp" alt="image-20210301165614422"></p><p>效果：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/image-20210301165652352.9ckdcynqzbw.webp" alt="image-20210301165652352"></p><h2 id="IDEA-设置代理"><a href="#IDEA-设置代理" class="headerlink" title="IDEA 设置代理"></a>IDEA 设置代理</h2><p>在 <code>File | Settings | Appearance &amp; Behavior | System Settings | HTTP Proxy</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/proxy.36qs02yyvhk0.webp" alt="proxy"></p><p>然后点击 <code>Check connection</code> 输入 <a href="https://www.youtube.com/">YouTube</a> 的网址验证是否成功</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/youtube.66mlb9fk0xk0.webp" alt="youtube"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/success.1x9f47kzlry8.webp" alt="success"></p><p>还有另一种验证方式！就是使用 IDEA 的 HTTP Client</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/httpclient.phzumax9uds.webp" alt="httpclient"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7891a5c7/22.2iiok2okub80.webp" alt="images"></p><p>以上就是我个人对 IDEA 2020.3.2 的所有设置了</p>]]></content>
    
    
    <summary type="html">对 IDEA 进行设置，让开发的时候更加便利顺手，以下是我对 IDEA 的设置，可供参考，IDEA 版本 2020.3.2</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="IntelliJ IDEA" scheme="https://blog.imzjw.cn/tags/IntelliJ-IDEA/"/>
    
  </entry>
  
  <entry>
    <title>IDEA 2020.3.2 安装破解 MyBatis Log Plugin</title>
    <link href="https://blog.imzjw.cn/posts/e8de389e/"/>
    <id>https://blog.imzjw.cn/posts/e8de389e/</id>
    <published>2021-02-28T08:11:48.000Z</published>
    <updated>2021-02-28T08:11:48.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在此之前都是用的 <a href="https://confluence.jetbrains.com/display/IDEADEV/IntelliJ+IDEA+2018.3.6+(183.6156.11+build)+Release+Notes">IDEA 2018.3</a>，前几天才更新到了 <a href="https://confluence.jetbrains.com/display/IDEADEV/IntelliJ+IDEA+2020.3.2+%28203.7148.57+build%29+Release+Notes">2020.3.2</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e8de389e/20210228172355.143hxnyecekg.webp" alt="images"></p><p>但是在进行同步插件的时候，oh shit!!!  我发现 <code>MyBatis Log Plugin</code> 居然开始收费了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e8de389e/image-20210228161703899.5lqthtro3mc0.webp" alt="img"></p><p>心想，难道我要回退到之前的版本吗？可是人家又不想，2020.3 版本我太喜欢了，随后我就跑去 GitHub 搜有没有什么方法可以免费使用 <code>MyBatis Log Plugin</code> 结果还真给我搜到了，<em>thank goodness</em> 🙏</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e8de389e/img.3l3wsc0ibke0.webp" alt="img"></p><h2 id="What-is-MyBatis-Log-Plugin"><a href="#What-is-MyBatis-Log-Plugin" class="headerlink" title="What is MyBatis Log Plugin?"></a>What is MyBatis Log Plugin?</h2><p>安装之前简单的说下 <code>MyBatis Log plugin?</code> 是什么</p><p>其实就是查看执行了哪些 SQL，把这条 SQL 拼接起来，然后我们就可以进行执行测试，非常的方便，再也不用把各个参数复制出来，手动补到 <code>?</code> 占位符中执行测试</p><h2 id="开始安装"><a href="#开始安装" class="headerlink" title="开始安装"></a>开始安装</h2><p>先去下载插件，任选其一</p><div class="btns rounded grid5">            <a class="button" href='https://github.com/Link-Kou/intellij-mybaitslog/releases' title='下载地址一'><i class='fas fa-download'></i>下载地址一</a><a class="button" href='https://odpan.ml/Software/Windows/Develop/IntelliJ%20IDEA/Plugin/MyBatis%20Log%20Plugin/' title='下载地址二'><i class='fas fa-download'></i>下载地址二</a>          </div><p>随后打开 IDEA 左上角 <code>File -&gt; Settings -&gt; Plugins</code> 右侧找到小齿轮，点击 <code>Install Plugin from Disk...</code> 然后选择刚刚下载的插件</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e8de389e/image-20210228164526063.l8saf3xztww.webp" alt="img"></p><p>如此如此，就安装完成了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e8de389e/image-20210228165713485.65f9n3gm70g0.webp" alt="img"></p><h2 id="怎么使用？"><a href="#怎么使用？" class="headerlink" title="怎么使用？"></a>怎么使用？</h2><p>安装成功之后会有个 <code>MyBatis Log</code> 的 toolbar，点击即可查看</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e8de389e/image-20210228170725974.75m560ad1qg0.webp" alt="console"></p><div class="note warning flat"><p>前提是要开启日志，不然不会有任何显示的</p></div>]]></content>
    
    
    <summary type="html">在此之前都是用的 IDEA 2018.3，前几天才更新到了 2020.3.2，但是在进行同步插件的时候，oh shit!!! 我发现 MyBatis Log Plugin 居然开始收费了</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="IntelliJ IDEA" scheme="https://blog.imzjw.cn/tags/IntelliJ-IDEA/"/>
    
  </entry>
  
  <entry>
    <title>Windows 修改 MySQL 5.7 默认字符集</title>
    <link href="https://blog.imzjw.cn/posts/bc202eb7/"/>
    <id>https://blog.imzjw.cn/posts/bc202eb7/</id>
    <published>2021-02-27T04:40:59.000Z</published>
    <updated>2021-02-27T04:40:59.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>MySQL 安装完成之后默认的字符集是 <code>latin1</code>，而它是不支持中文的，所以当插入的数据有中文时，会出现乱码或者无法插入到数据库中。</p><p>MySQL 5.5 版本以后，要使用 <code>utf8mb4</code> ，而不是 <code>utf8</code></p><p>因此我们需要修改 MySQL 的默认字符集为 <code>utf8mb4</code></p><h2 id="连接-MySQL"><a href="#连接-MySQL" class="headerlink" title="连接 MySQL"></a>连接 MySQL</h2><p>这里我用 <code>Navicat for MySQL</code> 进行连接登录</p><p>连接成功之后输入如下命令查看 MySQL 的默认字符集</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">show</span> variables <span class="keyword">like</span> <span class="string">&#x27;%char%&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/bc202eb7/213s.g937d9600lc.webp" alt="images"></p><h2 id="修改-my-ini-文件"><a href="#修改-my-ini-文件" class="headerlink" title="修改 my.ini 文件"></a>修改 my.ini 文件</h2><p>Win + R 输入 <code>C:\ProgramData\Mysql\Mysql Server 5.7\</code> 打开目录下的 <code>my.ini</code> 进行修改</p><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">[client]</span></span><br><span class="line"><span class="attr">default-character-set</span>=utf8mb4</span><br><span class="line"></span><br><span class="line"><span class="section">[mysql]</span></span><br><span class="line"><span class="attr">default-character-set</span>=utf8mb4</span><br><span class="line"></span><br><span class="line"><span class="section">[mysqld]</span></span><br><span class="line"><span class="attr">character-set-server</span>=utf8mb4</span><br><span class="line"><span class="attr">collation-server</span>=utf8mb4_unicode_ci</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/bc202eb7/bbbbb.6nvi7s17l9k0.webp" alt="images"></p><p>重启 MySQL</p><p>你可以 <kbd>Win</kbd>+ <kbd>X</kbd> 按 <kbd>A</kbd> 进入 <code>Windows PowerShell</code></p><p>输入如下命令</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">net stop MySQL57</span><br><span class="line">net start MySQL57</span><br></pre></td></tr></table></figure><p>也可以 <kbd>Win</kbd> + <kbd>R</kbd> 输入 <code>services.msc</code> 进入服务之后按 <kbd>M</kbd> 找到 MySQL 随后重启动此服务</p><p>重启完成之后打开 <code>Navicat for MySQL</code> 再次输入 <code>show variables like &#39;%char%&#39;;</code> 查看字符集</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/bc202eb7/bqweqw.6gdf3bzt8280.webp" alt="images"></p><p>之后创建数据库的时候，默认就是 <code>utf8mb4</code> 了</p><div class="note warning flat"><p>注：如果修改之后还是不成功，那就把 <code>my.ini</code> 文件复制一份到 MySQL 的安装目录</p></div><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/bc202eb7/bnm.4sq46n23zse0.webp" alt="images"></p>]]></content>
    
    
    <summary type="html">MySQL 安装完成之后默认的字符集是 latin1，而它是不支持中文的，所以当插入的数据有中文时，会出现乱码或者无法插入到数据库中。MySQL 5.5 版本以后，要使用 utf8mb4</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="MySQL" scheme="https://blog.imzjw.cn/tags/MySQL/"/>
    
  </entry>
  
  <entry>
    <title>使用 Spring Boot 组件动态修改日志级别</title>
    <link href="https://blog.imzjw.cn/posts/22b8ebdd/"/>
    <id>https://blog.imzjw.cn/posts/22b8ebdd/</id>
    <published>2021-02-21T07:38:16.000Z</published>
    <updated>2021-02-21T07:38:16.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在日常工作中，我们为了方便定位问题通常都会打印日志，在开发、测试和生产环境中，日志级别可能都不一样，而在自己开发的过程中为了方便调试可能会打印很多日志，但是生产中为了性能这些日志我们可能需要删掉，只保留一些必要的日志</p><p><code>Log4j</code> 定义了 8 个日志级别，其中的日志级别优先级从高到低为：</p><ul><li>OFF</li><li>FATAL</li><li>ERROR</li><li>WARN</li><li>INFO</li><li>DEBUG</li><li>TRACE</li><li>ALL</li></ul><p>从 <code>Spring Boot@1.5</code> 版本开始，<a href="https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html">Spring Boot Actuator</a> 组件就提供了动态修改日志级别的能力</p><p>本篇文章讲下如何动态的修改日志的级别，不用重启项目直接给日志降级或者升级 👏</p><h2 id="正式开始"><a href="#正式开始" class="headerlink" title="正式开始"></a>正式开始</h2><p>首先创建一个 Spring Boot 项目</p><p>添加依赖（<code>pom.xml</code>）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-actuator<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure><p><code>new</code> 一个测试类（<code>cn.imzjw.log.controller.LogController.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.imzjw.log.controller;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.slf4j.Logger;</span><br><span class="line"><span class="keyword">import</span> org.slf4j.LoggerFactory;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.GetMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RestController;</span><br><span class="line"></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Logger</span> <span class="variable">LOGGER</span> <span class="operator">=</span> LoggerFactory.getLogger(LogController.class);</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;/log&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">simple</span><span class="params">()</span> &#123;</span><br><span class="line">        LOGGER.debug(<span class="string">&quot;output debug log...&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;debug&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>application.yml</code></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">management:</span></span><br><span class="line">  <span class="attr">endpoints:</span></span><br><span class="line">    <span class="attr">web:</span></span><br><span class="line">      <span class="attr">exposure:</span></span><br><span class="line">        <span class="attr">include:</span> <span class="string">&#x27;loggers&#x27;</span></span><br></pre></td></tr></table></figure><h3 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h3><p><code>/loggers</code> 接口提供了查看以及修改日志级别的能力</p><p>在浏览器打开 <code>http://localhost:8080/actuator/loggers</code> 查看当前应用所有包和类的日志级别</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/22b8ebdd/01.7l21bjrxms0.webp" alt="img"></p><p>那么如何查看指定包和类的日志呢？</p><p>浏览器打开 <code>http://localhost:8080/actuator/loggers/cn.imzjw.log.controller.LogController</code></p><p>注意替换成自己的<code>包名</code>以及<code>类名</code></p><p>结果可以看出我们的日志级别是 <code>INFO</code></p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;configuredLevel&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">null</span></span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;effectiveLevel&quot;</span><span class="punctuation">:</span> <span class="string">&quot;INFO&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><h3 id="修改日志级别"><a href="#修改日志级别" class="headerlink" title="修改日志级别"></a>修改日志级别</h3><p>在我们的测试类中的接口，打印了一条 <code>LOGGER.debug(&quot;output debug log...&quot;);</code> 而上面的结果显示我们的日志级别是 <code>INFO</code>，所以这个 <code>DEBUG</code> 日志是不会打印的，不信我们测试一下</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/22b8ebdd/02.4cz28dm2cqu0.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/22b8ebdd/03.1roy3ijwf3a8.webp" alt="img"></p><p>不管我怎么请求这个接口，控制台依然没打印这个日志</p><p>下面我们就把这个日志级别修改成 <code>DEBUG</code> 级别</p><p>你可以使用 <a href="https://www.postman.com/">Postman</a> 工具，也可以直接使用命令行的方式，不管用啥，只要能请求到就行</p><p>这里我懒得打开 Postman 了，就直接用命令行的方式了</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">curl -X POST http://localhost:8080/actuator/loggers/cn.imzjw.log.controller.LogController \</span><br><span class="line">-H <span class="string">&quot;Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8&quot;</span> \</span><br><span class="line">--data <span class="string">&#x27;&#123;&quot;configuredLevel&quot;:&quot;debug&quot;&#125;&#x27;</span></span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/20240503/blogimage.70a57w14ug.webp" alt="blogimage"></p><p>然后浏览器打开访问 <code>http://localhost:8080/actuator/loggers/cn.imzjw.log.controller.LogController</code> 注意换成自己的<code>包名</code>和<code>类名</code></p><p>可以发现是 <code>DEBUG</code> 级别了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/20240503/blogimage.5j4064xi70.webp" alt="blogimage"></p><p>这个时候我们再来访问那个 <code>LogController</code>，可以发现控制台成功打印 <code>DEBUG</code> 日志了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/20240503/blogimage.361doxk2re.webp" alt="blogimage"></p><div class="note warning flat"><p>注：上面是使用了 <code>Postman</code> 和 <code>curl</code> 的方式修改日志级别，这些方式都不适用于生产环境，因为很麻烦，容易出错</p></div><p>一般我们可以使用 <code>Spring Boot Admin</code> 可视化修改日志级别，这个可以自己研究，又或者改天我水一篇 <code>Spring Boot Admin</code> 的</p><p>告辞!!!</p>]]></content>
    
    
    <summary type="html">在日常工作中，我们为了方便定位问题通常都会打印日志，在开发、测试和生产环境中，日志级别可能都不一样，而在自己开发的过程中为了方便调试可能会打印很多日志</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring Boot" scheme="https://blog.imzjw.cn/tags/Spring-Boot/"/>
    
  </entry>
  
  <entry>
    <title>如何零成本挂载 OneDrive</title>
    <link href="https://blog.imzjw.cn/posts/cf-onedrive/"/>
    <id>https://blog.imzjw.cn/posts/cf-onedrive/</id>
    <published>2021-02-16T12:38:35.000Z</published>
    <updated>2021-02-16T12:38:35.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在此之前，看过很多挂载 OneDrive 的，但是基本都要服务器，而不用服务器的也有，就是 UI 稍差了点，就比如 <a href="https://github.com/heymind/OneDrive-Index-Cloudflare-Worker">【OneDrive-Index-Cloudflare-Worker】</a> 作者已经不维护了，除此之外还有一个较好看的 <a href="https://github.com/ukuq/onepoint">【onepoint】</a> 用的是 Vercel，但我还是觉得 <a href="https://github.com/spencerwooo/onedrive-cf-index">【onedrive-cf-index】</a>好看（每个人眼光都不一样）用的是 Cloudflare，网上的教程看了下都是之前的，用的 <a href="https://firebase.google.com/">FireBase</a>，因为在那时 Cloudflare KV 存储是要钱的，还挺贵，而现在 KV 免费 1 GB 啦，所以我无聊就写一写 onedrive-cf-index 的教程，虽然官方也有教程，但是我总觉得他那个<a href="https://github.com/spencerwooo/onedrive-cf-index/blob/master/README-CN.md">【中文文档】</a>是机翻…好了，不废话了</p><h2 id="预览"><a href="#预览" class="headerlink" title="预览"></a>预览</h2><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/a02ad2cb760f6d070f525c427f119637.webp" alt="onedrive-cf-index"></p><ul><li><a href="https://cf.odpan.ml/">预览地址</a></li></ul><h2 id="正式开始"><a href="#正式开始" class="headerlink" title="正式开始"></a>正式开始</h2><div class="note danger flat"><p>本文教程只是针对普通版的 OneDrive，世纪互联的出了问题可以提 <a href="https://github.com/spencerwooo/onedrive-cf-index/issues/new">issues</a> 或者 Look Look 有没有同样错误的 <a href="https://github.com/spencerwooo/onedrive-cf-index/issues?q=is:issue+is:closed">issues</a></p></div><h3 id="获取-client-id"><a href="#获取-client-id" class="headerlink" title="获取 client_id"></a>获取 client_id</h3><p>点击 <a href="https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade">Microsoft Azure App registrations</a></p><p>输入账号密码后选择新注册，名称随便填，账户类型选择第二个，重定向 URI 默认就是 Web，地址填 <del><code>https://heymind.github.io/tools/microsoft-graph-api-auth</code></del> （不知道从什么时候，地址填这个打开网站会出现  <code>Error 1101</code>，业余时间研究了一下，得知这里要填 <code>http://localhost</code>） 然后点击注册</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/8f554bcb604d2ccbf39eee193e41a905.webp" alt="img"></p><p>注册成功之后你就能看到你的 <code>client_id </code> 了，记在小本本上，一会要用到</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/606c09c0e154e53b2d97a944f4f61d3e.webp" alt="img"></p><h3 id="获取-client-secret"><a href="#获取-client-secret" class="headerlink" title="获取 client_secret"></a>获取 client_secret</h3><p>点击证书和密码</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/5f8e1c721eda2d386234e3cf2a4f1306.webp" alt="img"></p><p>期限要选择<code>从不</code>，名字可以随便乱取，然后选择添加即可</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/9f427a8dd99a4adf86efffb588ab0062.webp" alt="img"></p><p>复制该 <code>Value</code> 值，只会显示一次，记在小本本上，会用到，这时相信你已经成功获取到了 <code>client_id</code> 和 <code>client_secret</code> 了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/e2f9e4d49b9fba5c9552caa8cda46628.webp" alt="img"></p><h3 id="获取-API-权限"><a href="#获取-API-权限" class="headerlink" title="获取 API 权限"></a>获取 API 权限</h3><p>点击 API 权限，选择三个权限，分别是 <code>offline_access</code>、<code>Files.Read</code>、<code>Files.Read.All</code>，最后点击更新权限</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/2f520f2e621a163b27df4917d27d962c.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/add_api.1dzqobw1ofa8.webp" alt="add_api"></p><h3 id="获取-refresh-token"><a href="#获取-refresh-token" class="headerlink" title="获取 refresh_token"></a>获取 refresh_token</h3><ol><li><p>打开 <a href="https://heymind.github.io/tools/microsoft-graph-api-auth">https://heymind.github.io/tools/microsoft-graph-api-auth</a></p></li><li><p>在 <code>4.Authorize for code</code> 输入刚刚获取的 <code>client_id</code> 并点击 <code>AUTHORIZE</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/c546f51bf081104e177c076d06fa4eca.webp" alt="Authorize for code"></p><p>登录 Microsoft 账户，并允许授权，就会得到一串 Code</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/11b6f4028cac51f9f610650dfce7ca3c.webp" alt="Code"></p></li><li><p>在 <code>5.Exchange Access Token</code> 输入刚刚获取的 <code>client_secret</code> 并点击 <code>GET TOKEN</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/9d3997ed0bae710672afb7116e63349e.webp" alt="img"></p><p>如果没啥错误，那就复制 <code>refresh_token</code> 并记在小本本上，可以 <kbd>CTRL</kbd> + <kbd>F</kbd> 搜索 refresh_token</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/dc3292609f55a51f1d84427f641abd8e.webp" alt="refresh_token"></p><p>如果出现 <code>error: &quot;invalid_request&quot;</code> 的错误，解决办法可以用 <code>post</code> 工具，先去下载安装好 <a href="https://www.postman.com/downloads/">Postman</a></p><p>在 postman 中新建个请求页面，请求类型设置为 POST，地址输入：<code>https://login.microsoftonline.com/common/oauth2/v2.0/token</code>，下面选择 <code>Body</code> 选项卡，下面那一栏选中 <code>application/x-www-form-urlencoded</code>，然后添加五个参数</p><ul><li><code>grant_type</code> 填 authorization_code</li><li><code>code</code> 填刚刚获取的 <code>authorization code</code></li><li><code>redirect_uri</code> 填 <code>https://heymind.github.io/tools/microsoft-graph-api-auth</code></li><li><code>client_id</code> 就是 client_id 呗</li><li><code>client_secret</code> 就是 client_secret 呗</li></ul><p>点击 <code>Send</code>，不出意外的话，就会有 <code>access_token</code> 和 <code>refresh_token</code>，把 <code>refresh_token</code> 记在小本本上！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/postman.iv0upqmz8ko.webp" alt="postman"></p></li></ol><p>准备工作都已完成了，我们已经获取到了必要的 <code>client_id</code>、<code>client_secret</code> 以及 <code>refresh_token</code></p><p>现在就开始配置 Cloudflare 了</p><h3 id="配置-Cloudflare"><a href="#配置-Cloudflare" class="headerlink" title="配置 Cloudflare"></a>配置 Cloudflare</h3><p>首先克隆 onedrive-cf-index 项目</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com.cnpmjs.org/spencerwooo/onedrive-cf-index.git</span><br></pre></td></tr></table></figure><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> onedrive-cf-index</span><br><span class="line"><span class="comment"># 安装依赖</span></span><br><span class="line">npm install</span><br></pre></td></tr></table></figure><p>安装 CloudFlare Workers 官方编译部署工具</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i @cloudflare/wrangler -g</span><br></pre></td></tr></table></figure><p>使用 wrangler 登录 Cloudflare 账户</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wrangler login</span><br></pre></td></tr></table></figure><p>查看登录状态</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wrangler whoami</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/c0322b2d5ec97e9c5234a242f340b191.webp" alt="登录状态"></p><p>登录 <a href="https://dash.cloudflare.com/login">Cloudflare</a>，点击域名，滚轮往下滑，在右侧，复制 <code>account_id</code>（账户 ID）以及 <code>zone_id</code>（区域 ID）</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/47cbceef2a2a3b5117b1816f431e66fa.webp" alt="img"></p><p>紧接着创建一个默认的 Worker</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/c8ee98d1591d389e09a51efcbb17c282.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/e391afb0a0657203e4e42abe619805ee.webp" alt="img"></p><p>在 onedrive-cf-index 项目的根目录中找到 <code>wrangler.toml</code> 并修改 <code>name</code>、<code>account_id</code> 以及 <code>zone_id</code></p><div class='checkbox green checked'><input type="checkbox" checked="checked"/>            <p>name：就是我们刚刚创建默认的 Worker 名称</p>            </div><div class='checkbox green checked'><input type="checkbox" checked="checked"/>            <p>account_id：Cloudflare 账户 ID</p>            </div><div class='checkbox green checked'><input type="checkbox" checked="checked"/>            <p>zone_id：Cloudflare 区域 ID</p>            </div><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/3f9b73f046202780dbe59bf2dca3ac59.webp" alt="img"></p><p>接着创建一个叫 <code>BUCKET</code> 的 Cloudflare Workers KV bucket</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wrangler kv:namespace create <span class="string">&quot;BUCKET&quot;</span></span><br></pre></td></tr></table></figure><p>然后就会生成个 <code>ID</code></p><p>如果你需要本地预览的话，输入以下命令，不需要就不用管</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wrangler kv:namespace create <span class="string">&quot;BUCKET&quot;</span> --preview</span><br></pre></td></tr></table></figure><p>继续修改 <code>wrangler.toml</code> 找到里面的 <code>kv_namespaces</code>，并吧刚刚生成的 ID 复制粘贴到 id 处</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/a42b16ae0d3203911392bc317941b32f.webp" alt="img"></p><p>由于我不需要本地预览，所以我把 <code>preview_id</code> 删了也没事</p><p>修改 <code>./src/config/default.js</code></p><ul><li><p>client_id：刚刚让你记在小本本上的 <code>client_id</code></p></li><li><p>base：就是个路径，意思就是你要挂载的目录，如果你想挂载根目录的话，那就写 <code>/</code>，挂载某个文件夹的话那就填某个文件夹的名称，比如 <code>/Public</code>（我只想挂载 <code>Public</code> 里面的内容）</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/7f5554c802bb36e9e2c59533fe584b34.webp" alt="img"></p></li></ul><p>使用 <code>wrangler</code> 添加 Cloudflare Workers 环境变量</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wrangler secret put CLIENT_SECRET<span class="comment"># 回车之后粘贴你的 client_secret</span></span><br></pre></td></tr></table></figure><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wrangler secret put REFRESH_TOKEN<span class="comment"># 回车之后粘贴你的 refresh_token</span></span><br></pre></td></tr></table></figure><p>在添加 <code>refresh_token</code> 环境变量时，很不幸出现了个错误</p><p><code>Your secret is too large, it must be 1kB or less</code></p><p>意思就是说 refresh_token 的值超过 <code>1 KB</code> 了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/c35cc0f9e45d8d6cce18e69ba6e64cd2.webp" alt="img"></p><p>不过没事，我们换一种方法获取 refresh_token</p><p>在 Cloudflare Workers → KV 里面的 BUCKET 中创建一个新的名称，叫 refresn_token，然后 Value 输入你的 refresn_token</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/17a8a343fe09d845d45caff091e8fce0.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/0bb7c475a50a91a87326da48436dfaf6.webp" alt="img"></p><p>接着修改代码，在 <code>./src/auth/onedrive.js</code> 里面加一个获取 <code>refresh_token</code> 的代码</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> refresh_token = <span class="keyword">await</span> <span class="variable constant_">BUCKET</span>.<span class="title function_">get</span>(<span class="string">&#x27;refresh_token&#x27;</span>)</span><br></pre></td></tr></table></figure><p>后面所有 <code>config.refresh_token</code> 的都直接改为 <code>refresh_token</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/e7fa15779f374c0b63b99ac9722a42ac.webp" alt="img"></p><p>紧接着在 <code>./src/config/default.js</code> 里，把原有定义的 refresh_token 删掉或者注释掉</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/8388166470425e1b8fcc1f64d0cc653c.webp" alt="img"></p><p>最后使用如下命令发布 Cloudflare Worker</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wrangler publish</span><br></pre></td></tr></table></figure><p>大功告成!!!</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cf-onedrive/a02ad2cb760f6d070f525c427f119637.webp" alt="img"></p>]]></content>
    
    
    <summary type="html">在此之前，看过很多挂载 OneDrive 的，但是基本都要服务器，而不用服务器的也有，就是 UI 稍差了点，就比如 OneDrive-Index-Cloudflare-Worker 作者已经不维护了，除此之外还有一个较好看的 onepoint</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="Microsoft" scheme="https://blog.imzjw.cn/tags/Microsoft/"/>
    
  </entry>
  
  <entry>
    <title>介绍一个 GitHub + jsDelivr 图床神器</title>
    <link href="https://blog.imzjw.cn/posts/8f9a47ec/"/>
    <id>https://blog.imzjw.cn/posts/8f9a47ec/</id>
    <published>2021-02-09T08:57:15.000Z</published>
    <updated>2021-02-09T08:57:15.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>像最原始用 GitHub + jsDelivr 的时候，一推图片 commit、push，然后浏览器访问 <code>https://cdn.jsdelivr.net/gh/用户名/仓库名@分支/</code> 点来点去再复制图片的链接，这真的是非常的繁琐，后来有了 <a href="https://github.com/Molunerfinn/PicGo">PicGo</a> ，这大大的让我们简便了许多，再后来又有了 <a href="https://github.com/yumusb/autoPicCdn">autoPicCdn</a>，这让我们无需下载安装，直接网页上使用。</p><p>而今天无意中发现了一款基于 GitHub API 的免费、稳定且高效的图床管理神器。图片外链使用 <code>jsDelivr</code> 进行 CDN 加速，免下载安装，打开网站即可使用</p><p>这让我放弃了 autoPicCdn，为什么呢？</p><ol><li><p>autoPicCdn 是 PHP 写的， 得要虚拟主机，虽然也有很多免费的，这个不重要，主要是我号多，每次上传我还得跑去 <code>up.php</code> 改配置…所以我就弄了三台虚拟主机且还不够，域名嘛，倒无所谓，整几个 Freenom 的免费域名就好</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8f9a47ec/image-20210209160547927.3jxrniejqr60.webp" alt="img"></p></li><li><p>图片没有管理</p></li></ol><h2 id="开始使用"><a href="#开始使用" class="headerlink" title="开始使用"></a>开始使用</h2><p>今天介绍的这个图床神器也就是 <a href="https://github.com/XPoet/picx">picx</a></p><p>首先这个项目是基于 Vue 写的，这点我就很喜欢，而且无需服务器，你可以打开 picx 的网站，直接使用，地址：<a href="https://picx.xpoet.cn/">https://picx.xpoet.cn/</a></p><p>怎么使用，作者的 <a href="https://github.com/XPoet/picx/blob/master/README.md#how-to-use-%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8">README.md</a> 也讲的非常清楚，照着做即可</p><p>而本篇文章不只是介绍，而是搭建一个自用的图床神器，不想麻烦的你可以直接打开 picx 的网站即可使用</p><h3 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h3><p>我分为 5 点</p><ol><li>克隆项目，本地调式</li><li>创建仓库（分为源码仓库和生成的静态仓库，注意是俩仓库）</li><li>修改 <code>.travis.yml</code></li><li>部署到 Vercel</li><li>完成搭建</li></ol><h3 id="克隆项目"><a href="#克隆项目" class="headerlink" title="克隆项目"></a>克隆项目</h3><ol><li>项目地址：<a href="https://github.com/XPoet/picx">https://github.com/XPoet/picx</a></li><li>随便在哪 <code>git clone https://github.com.cnpmjs.org/XPoet/picx.git</code></li><li>在 picx 根目录中执行 <code>npm install</code></li><li>执行 <code>npm run serve</code> 进行本地调式，默认端口是 8080</li><li>收工</li></ol><h3 id="创建仓库"><a href="#创建仓库" class="headerlink" title="创建仓库"></a>创建仓库</h3><p>这里需要俩仓库</p><p>一：源码仓库</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8f9a47ec/image-20210209164201690.470wi12q6u00.webp" alt="源码仓库"></p><p>二：是打包之后生成的 <code>dist</code> 目录的仓库，就是个空仓库，可以这么理解：由持续集成帮你 <code>push</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8f9a47ec/image-20210209170759458.1fyqem0spr1c.webp" alt="静态仓库"></p><p>当然你可以不这么做，甚至你可以在 picx 根目录执行 <code>npm run build</code> 之后吧生成的 dist 目录直接 push，随后导入到 Vercel 并自定义域名大功告成</p><h3 id="修改-travis-yml"><a href="#修改-travis-yml" class="headerlink" title="修改 .travis.yml"></a>修改 .travis.yml</h3><p>因为我要部署在 Vercel 嘛，故这里修改一下</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 编译语言、环境</span></span><br><span class="line"><span class="attr">dist:</span> <span class="string">xenial</span></span><br><span class="line"><span class="attr">os:</span> <span class="string">linux</span></span><br><span class="line"><span class="attr">language:</span> <span class="string">node_js</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Node.js 版本</span></span><br><span class="line"><span class="attr">node_js:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="number">12</span></span><br><span class="line"></span><br><span class="line"><span class="attr">cache:</span> <span class="string">npm</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 只有 master 分支更改才触发 CI</span></span><br><span class="line"><span class="attr">branches:</span></span><br><span class="line">  <span class="attr">only:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">master</span></span><br><span class="line"></span><br><span class="line"><span class="attr">before_install:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">export</span> <span class="string">TZ=&#x27;Asia/Shanghai&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="attr">install:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">npm</span> <span class="string">install</span> <span class="comment"># 安装依赖</span></span><br><span class="line"></span><br><span class="line"><span class="attr">script:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">npm</span> <span class="string">run</span> <span class="string">build</span> <span class="comment"># 执行打包命令，生成 dist 静态文件</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">cd</span> <span class="string">./dist</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">git</span> <span class="string">init</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">git</span> <span class="string">config</span> <span class="string">user.name</span> <span class="string">&quot;$&#123;GIT_NAME&#125;&quot;</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">git</span> <span class="string">config</span> <span class="string">user.email</span> <span class="string">&quot;$&#123;GIT_EMAIL&#125;&quot;</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">git</span> <span class="string">add</span> <span class="string">.</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">git</span> <span class="string">commit</span> <span class="string">-m</span> <span class="string">&quot;update By garvey&quot;</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">git</span> <span class="string">push</span> <span class="string">--force</span> <span class="string">--quiet</span> <span class="string">&quot;https://$&#123;GH_TOKEN&#125;@$&#123;GH_REF&#125;&quot;</span> <span class="string">master:master</span></span><br></pre></td></tr></table></figure><p>修改完成之后，在 <a href="https://www.travis-ci.com/">travis-ci</a> 导入你的源码仓库，随后点击 <code>Settings</code> 设置变量</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8f9a47ec/xiaojia.9oodada2ddo.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8f9a47ec/bianliang.webp" alt="变量"></p><p>变量说明：</p><table><thead><tr><th align="center">NAME</th><th align="center">VALUE</th></tr></thead><tbody><tr><td align="center">GIT_NAME</td><td align="center">GitHub 用户名</td></tr><tr><td align="center">GIT_EMAIL</td><td align="center">邮箱</td></tr><tr><td align="center">GH_TOKEN</td><td align="center">去 <a href="https://github.com/settings/tokens/new">https://github.com/settings/tokens/new</a>  生成 TOKEN，勾选 repo 和 workflow</td></tr><tr><td align="center">GH_REF</td><td align="center">也就是刚刚创建打包生成的 dist 目录的仓库，格式为：github.com/用户名/仓库名.git</td></tr></tbody></table><p>配置完成后并 <code>push</code>，然后等待 travis 完成工作之后，静态仓库就有了打包之后的文件了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8f9a47ec/static-pic.webp" alt="static-pic"></p><h3 id="部署到-Vercel"><a href="#部署到-Vercel" class="headerlink" title="部署到 Vercel"></a>部署到 Vercel</h3><p>打开 <a href="https://vercel.com/">Vercel</a></p><p>导入刚刚的静态仓库</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8f9a47ec/vercel-1.webp" alt="vercel-1"></p><p>满屏的烟花说明成功了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8f9a47ec/vercel-2.webp" alt="vercel-2"></p><p>我们点击 View Domains 自定义域名</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8f9a47ec/vercel-3.webp" alt="vercel-3"></p><p>输入自己的域名并点击右侧的 Add，随后根据它的提示进行域名解析，你也可以使用 Vercel 提供的二级域名，格式为 <code>xxx.now.sh</code> \ <code>xxx.vercel.app</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8f9a47ec/vercel-4.webp" alt="vercel-4"></p><h3 id="完成搭建"><a href="#完成搭建" class="headerlink" title="完成搭建"></a>完成搭建</h3><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8f9a47ec/success.650augcixm80.webp" alt="success"></p><p>说实话这个管理我真的是太爱了，可以切换到不同的目录进行管理</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/8f9a47ec/guanli.62xnykf4qxw0.webp" alt="管理"></p>]]></content>
    
    
    <summary type="html">像最原始用 GitHub + jsDelivr 的时候，一推图片 commit、push，然后浏览器访问 https://cdn.jsdelivr.net/gh/用户名/仓库名@分支/ 点来点去再复制图片的链接，这真的是非常的繁琐</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="图床" scheme="https://blog.imzjw.cn/tags/%E5%9B%BE%E5%BA%8A/"/>
    
  </entry>
  
  <entry>
    <title>关于我 Butterfly 主题的所有美化</title>
    <link href="https://blog.imzjw.cn/posts/b74f504f/"/>
    <id>https://blog.imzjw.cn/posts/b74f504f/</id>
    <published>2021-02-03T09:58:22.000Z</published>
    <updated>2021-09-28T11:50:10.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>折腾 Butterfly 主题也有一年多了，也是时候写篇文章记录一下本站的所有美化，美化过的一点一滴都会记录在此篇文章里，后续也会在此篇文章更新！</p><p>PS：基本没修改过源码！本博主 <span class="inline-tag blue">Butterfly</span> 版本 <span class="inline-tag red">3.7.7</span></p><p>适用人群：Butterfly 主题使用者！</p><h2 id="首页背景图"><a href="#首页背景图" class="headerlink" title="首页背景图"></a>首页背景图</h2><details class="folding-tag" green><summary> 查看预览 </summary>              <div class='content'>              <p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/5022d5eec59b85fec10efe3d7e580cdb.webp" alt="images"></p>              </div>            </details><details class="folding-tag" green><summary> 配置 </summary>              <div class='content'>              <p>这个背景图其实很简单，在主题的配置文件（<code>_config.yml</code>）里，<kbd>CTRL</kbd> + <kbd>F</kbd> 找到 <code>index_img</code> 配置项，修改它即可<img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/2525870ecc78db695eb5fcd7a6e69762.webp" alt="img"></p>              </div>            </details><h2 id="首页字体"><a href="#首页字体" class="headerlink" title="首页字体"></a>首页字体</h2><details class="folding-tag" green><summary> 查看预览 </summary>              <div class='content'>              <p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/167a25f94ffd74396dc25d848b61214d.webp" alt="img"> </p>              </div>            </details><details class="folding-tag" green><summary> 配置 </summary>              <div class='content'>              <p>这个就需要你自己新建一个 <code>css</code> 文件，在主题文件里的 <code>source \ css</code> 文件夹里新建一个 <code>css</code> 文件，命名随意</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/6038e32a4cc2223811c38ae9723d72d5.webp" alt="img"></p><p>往里写几行代码就完事了</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">@font-face</span> &#123;</span><br><span class="line">    <span class="attribute">font-family</span>:<span class="string">&#x27;arzhu&#x27;</span>;</span><br><span class="line">    <span class="attribute">src</span>:<span class="built_in">url</span>(<span class="string">&#x27;https://cdn.jsdelivr.net/gh/xxx/xxx/font/xxx.ttf&#x27;</span>); <span class="comment">/* 修改成你的字体 */</span></span><br><span class="line">    <span class="attribute">font-display</span>:swap</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">h1</span><span class="selector-id">#site-title</span> &#123;</span><br><span class="line">    <span class="attribute">font-family</span>:arzhu<span class="meta">!important</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">span</span><span class="selector-id">#subtitle</span> &#123;</span><br><span class="line">    <span class="attribute">font-family</span>:arzhu<span class="meta">!important</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">a</span><span class="selector-id">#site-name</span> &#123;</span><br><span class="line">    <span class="attribute">font-family</span>:arzhu<span class="meta">!important</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里推荐俩字体网站</p><ul><li><a href="https://www.100font.com/">100 font</a> </li><li><a href="http://www.diyiziti.com/list">第一字体</a></li></ul><p>挑选您心爱的字体，并把它下载下来，可以存在本地，也可以利用 <code>jsdelivr</code> 的方式加速，最后替换 css 文件中的 url 即可，<code>arzhu</code> 只是别名，可以任意修改，不过引用的时候，要确保名字相同</p><p>最后在主题的配置文件里找到 <code>inject</code> 配置项，引用刚刚新建的 css 文件即可</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/26351165f1e020ba491b468fadf06fe0.webp" alt="img"></p><p>href 这里我是采用 CDN 的方式，如果你是存在本地的话，那么此时的 href 就应该是</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> <span class="string">&lt;link</span> <span class="string">rel=&quot;stylesheet&quot;</span> <span class="string">href=&quot;/css/custom.css&quot;</span> <span class="string">media=&quot;defer&quot;</span> <span class="string">onload=&quot;this.media=&#x27;all&#x27;&quot;&gt;</span></span><br></pre></td></tr></table></figure><p><code>media=&quot;defer&quot; onload=&quot;this.media=&#39;all&#39;&quot;</code>  这个只是 css 的异步加载，当然，你不写也可以！</p>              </div>            </details><h2 id="全局背景透明渐变"><a href="#全局背景透明渐变" class="headerlink" title="全局背景透明渐变"></a>全局背景透明渐变</h2><details class="folding-tag" green><summary> 查看预览 </summary>              <div class='content'>              <p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/829d069949364c2a0b6326a7ea2937ef.webp" alt="img"></p>              </div>            </details><details class="folding-tag" green><summary> 配置 </summary>              <div class='content'>              <p>同理，在刚刚新建的 css 文件里，添加如下代码</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-id">#recent-posts</span>&gt;<span class="selector-class">.recent-post-item</span>,<span class="selector-class">.layout_page</span>&gt;<span class="selector-tag">div</span><span class="selector-pseudo">:first</span>-child<span class="selector-pseudo">:not</span>(<span class="selector-class">.recent-posts</span>),<span class="selector-class">.layout_post</span>&gt;<span class="selector-id">#page</span>,<span class="selector-class">.layout_post</span>&gt;<span class="selector-id">#post</span>,<span class="selector-class">.read-mode</span> <span class="selector-class">.layout_post</span>&gt;<span class="selector-id">#post</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">var</span>(--light_bg_color)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#aside-content</span> <span class="selector-class">.card-widget</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">var</span>(--light_bg_color)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#web_bg</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">linear-gradient</span>(<span class="number">90deg</span>,<span class="built_in">rgba</span>(<span class="number">247</span>,<span class="number">149</span>,<span class="number">51</span>,.<span class="number">1</span>),<span class="built_in">rgba</span>(<span class="number">243</span>,<span class="number">112</span>,<span class="number">85</span>,.<span class="number">1</span>) <span class="number">15%</span>,<span class="built_in">rgba</span>(<span class="number">239</span>,<span class="number">78</span>,<span class="number">123</span>,.<span class="number">1</span>) <span class="number">30%</span>,<span class="built_in">rgba</span>(<span class="number">161</span>,<span class="number">102</span>,<span class="number">171</span>,.<span class="number">1</span>) <span class="number">44%</span>,<span class="built_in">rgba</span>(<span class="number">80</span>,<span class="number">115</span>,<span class="number">184</span>,.<span class="number">1</span>) <span class="number">58%</span>,<span class="built_in">rgba</span>(<span class="number">16</span>,<span class="number">152</span>,<span class="number">173</span>,.<span class="number">1</span>) <span class="number">72%</span>,<span class="built_in">rgba</span>(<span class="number">7</span>,<span class="number">179</span>,<span class="number">155</span>,.<span class="number">1</span>) <span class="number">86%</span>,<span class="built_in">rgba</span>(<span class="number">109</span>,<span class="number">186</span>,<span class="number">130</span>,.<span class="number">1</span>))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>              </div>            </details><h2 id="页脚透明渐变"><a href="#页脚透明渐变" class="headerlink" title="页脚透明渐变"></a>页脚透明渐变</h2><p>完成了如上全局背景透明渐变，那么你的部落格背景就应该会有所变化了，但是发现这个页脚和我们的背景完全不搭</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/52270629898ea9e22bdf9e4b9b67a482.webp" alt="img"></p><p>那我们就进行美化页脚部分</p><details class="folding-tag" green><summary> 查看预览 </summary>              <div class='content'>              <p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/1e5e0c8cd3ff7d46f2618310578affa5.webp" alt="img"></p>              </div>            </details><details class="folding-tag" green><summary> 配置 </summary>              <div class='content'>              <p>一样在刚刚新建的 <code>css</code> 文件里，添加如下代码</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-id">#footer</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">rgba</span>(<span class="number">255</span>,<span class="number">255</span>,<span class="number">255</span>,.<span class="number">15</span>);</span><br><span class="line">    <span class="attribute">color</span>: <span class="number">#000</span>;</span><br><span class="line">    <span class="attribute">border-top-right-radius</span>: <span class="number">20px</span>;</span><br><span class="line">    <span class="attribute">border-top-left-radius</span>: <span class="number">20px</span>;</span><br><span class="line">    backdrop-<span class="attribute">filter</span>: <span class="built_in">saturate</span>(<span class="number">100%</span>) <span class="built_in">blur</span>(<span class="number">5px</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#footer</span><span class="selector-pseudo">::before</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">rgba</span>(<span class="number">255</span>,<span class="number">255</span>,<span class="number">255</span>,.<span class="number">15</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#footer</span> <span class="selector-id">#footer-wrap</span> &#123;</span><br><span class="line">    <span class="attribute">color</span>: <span class="built_in">var</span>(--font-color)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#footer</span> <span class="selector-id">#footer-wrap</span> <span class="selector-tag">a</span> &#123;</span><br><span class="line">    <span class="attribute">color</span>: <span class="built_in">var</span>(--font-color)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>此时，页脚部分就和我们的背景很般配了</p>              </div>            </details><h2 id="社交图标"><a href="#社交图标" class="headerlink" title="社交图标"></a>社交图标</h2><details class="folding-tag" green><summary> 查看预览 </summary>              <div class='content'>              <p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/6067ce8c49c5b3bb68b3beffa5a782f5.webp" alt="img"></p>              </div>            </details><details class="folding-tag" green><summary> 配置 </summary>              <div class='content'>              <p>社交图标我采用的是阿里巴巴矢量图标库</p><p>首先打开 <a href="https://www.iconfont.cn/">阿里巴巴矢量图标库</a></p><p>在搜索框输入你想要的图标，比如 QQ</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/46b468e14f03045dc873f0fd6febd30f.webp" alt="img"></p><p>看中哪个就加入购物车</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/e28cfdf60a12635c3fe566ecaed17e51.webp" alt="img"></p><p>加购完毕之后点击右上角的购物车，添加至项目，选择其中一种快捷方式登录，项目名称随便填</p><p>然后在我的项目里选择 <code>Font class</code>，点击查看在线链接并在浏览器中打开此链接，最后另存为本地</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/bb1441dc69522135a0cbb9d081f70e30.webp" alt="img"></p><p>吧刚刚另存为的文件复制到主题文件下的 <code>source \ css</code> 里面</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/364620059e9fd381b5e4561b56ee0e0e.webp" alt="img"></p><p>然后在主题的配置文件（<code>_config.yml</code>）里的  <code>inject</code> 引入刚刚的图标 css 文件</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/396b8b60a5b775313fa5984bf57a2f70.webp" alt="img"></p><p>接着不要关闭配置文件，继续在配置文件里 <kbd>CTRL</kbd> + <kbd>F</kbd> 找到  <code>social</code>  配置项</p><p>格式为：iconfont class 名: 链接 || 名称</p><p>其中</p><ul><li><p>iconfont：是固定的</p></li><li><p>class 名：可在刚刚的阿里巴巴矢量图标库生成的 css 文件里找到</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/94a59cbf54e55fcef1ee8aaf79673fb4.webp" alt="img"></p></li><li><p>链接：点击图标之后跳转的链接</p></li><li><p>名称：对应你图标的含义，例如：Twitter、Facebook</p></li></ul><p>如下图：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/8626ddab3f0071100c45ccbc5576e506.webp" alt="img"></p><p>此时你高兴的回到首页查看效果，可是你发现这图标又小又丑又黑，心情都不好了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/88b5036cee2a28f35a36b1d9ed1a859a.webp" alt="img"></p><p>不慌，打开 <code>icon.css</code> 也就是刚刚在阿里巴巴矢量图标库中生成的 css 文件</p><p>给他们穿件衣裳</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/9bd36c1845fdd8cea9067c144984c74a.webp" alt="img"></p><p>果然，穿上衣裳就好看多了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/ef3de34f24c6d0ded83b51a179c8ab29.webp" alt="img"></p><p>如果你还想加其他的，比如微博、GitHub、哔哩哔哩等，其方法大同小异</p>              </div>            </details><h2 id="页脚徽标"><a href="#页脚徽标" class="headerlink" title="页脚徽标"></a>页脚徽标</h2><details class="folding-tag" green><summary> 查看预览 </summary>              <div class='content'>              <p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/footer.3xbuiwj2pnq0.webp" alt="footer"></p>              </div>            </details><details class="folding-tag" green><summary> 配置 </summary>              <div class='content'>              <p>这个挺简单的，可以直接通过 <a href="https://shields.io/">shields.io</a> 在线生成</p><ul><li>label：标签，徽标左侧内容</li><li>message：信息，徽标右侧内容</li><li>color：色值，支持支持十六进制、rgb、rgba、hsl、hsla 和 css 命名颜色。十六进制记得删除前面的 # 号</li></ul><p>输入相关信息后，点击 <code>make badge</code> 即可得到徽标的 URL。可以用 img 标签引用</p><p>接着打开主题的配置文件（_config.yml）找到 <code>custom_text</code> 配置项并修改它，最后建议把 footer 配置下的 copyright 设为 false</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/bda429f66a05f649e0c432c8dd55ae16.webp" alt="img"></p><p>我这里只是简单的举了个例子，想要啥就在 <a href="https://shields.io/">shields.io</a> 直接生成即可</p><p>示例：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;margin-inline:5px&quot;</span><span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span> <span class="attr">href</span>=<span class="string">&quot;https://hexo.io/&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://img.shields.io/badge/Frame-Hexo-blue?style=flat&amp;logo=hexo&quot;</span> <span class="attr">title</span>=<span class="string">&quot;博客框架为 Hexo&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;HEXO&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;margin-inline:5px&quot;</span><span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span> <span class="attr">href</span>=<span class="string">&quot;https://butterfly.js.org/&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://img.shields.io/badge/Theme-Butterfly-6513df?style=flat&amp;logo=bitdefender&quot;</span> <span class="attr">title</span>=<span class="string">&quot;主题采用 Butterfly&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;Butterfly&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;margin-inline:5px&quot;</span><span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span> <span class="attr">href</span>=<span class="string">&quot;https://www.jsdelivr.com/&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://img.shields.io/badge/CDN-jsDelivr-orange?style=flat&amp;logo=jsDelivr&quot;</span> <span class="attr">title</span>=<span class="string">&quot;本站使用 Jsdelivr 为静态资源提供CDN加速&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;Jsdelivr&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;margin-inline:5px&quot;</span><span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span> <span class="attr">href</span>=<span class="string">&quot;https://github.com/&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://img.shields.io/badge/Source-Github-d021d6?style=flat&amp;logo=GitHub&quot;</span> <span class="attr">title</span>=<span class="string">&quot;本站项目由 GitHub 托管&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;GitHub&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;margin-inline:5px&quot;</span><span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span><span class="attr">href</span>=<span class="string">&quot;http://creativecommons.org/licenses/by-nc-sa/4.0/&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://img.shields.io/badge/Copyright-BY--NC--SA%204.0-d42328?style=flat&amp;logo=Claris&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;img&quot;</span> <span class="attr">title</span>=<span class="string">&quot;本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br></pre></td></tr></table></figure>              </div>            </details><h2 id="关闭侧边栏"><a href="#关闭侧边栏" class="headerlink" title="关闭侧边栏"></a>关闭侧边栏</h2><p>这个其实官方文档也有讲，在某个页面如果你不想要侧边栏的话，可以在对应页面的 Markdown 里加如下配置</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title: 标签</span><br><span class="line">date: 2020-03-07 12:33:35</span><br><span class="line">type: &quot;tags&quot;</span><br><span class="line">comments: false</span><br><span class="line">aside: false&lt;-- 关闭侧边栏</span><br><span class="line"><span class="section">top<span class="emphasis">_img: false</span></span></span><br><span class="line"><span class="emphasis"><span class="section">---</span></span></span><br></pre></td></tr></table></figure><p>此时我们对应的页面就没有侧边栏了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/defb92b99112ee8b0eb25a0cd65c73e8.webp" alt="img"></p><h2 id="留言板信封"><a href="#留言板信封" class="headerlink" title="留言板信封"></a>留言板信封</h2><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/a82ff72b59ffa9b973f010a8bb058e24.gif" alt="message_gif"><div class="tabs" id="test2"><ul class="nav-tabs"><button type="button" class="tab " data-href="test2-1">旧版</button><button type="button" class="tab  active" data-href="test2-2">新版（推荐）</button></ul><div class="tab-contents"><div class="tab-item-content" id="test2-1"><p>首先最起码你得要有一个留言的页面</p><p>博客根目录右键 <code>Git Bash</code> 输入如下命令</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new page <span class="string">&quot;message&quot;</span></span><br></pre></td></tr></table></figure><p>接着在博客根目录的 <code>source</code> 下就会发现刚刚新建的文件了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/3489b206c1f19eda28b4068243bd8a47.webp" alt="images"></p><p>我们点进去打开  <code>index.md</code></p><p>复制如下代码，即可完事</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> <span class="attr">href</span>=<span class="string">&quot;https://npm.elemecdn.com/nanshen/css/blog/messagebar.css&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;computer&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;maincontent&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;form-wrap&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://npm.elemecdn.com/cover_img/msg/before.webp&quot;</span><span class="attr">id</span>=<span class="string">&quot;beforeimg&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;envelope&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">form</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;formmain&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">class</span>=<span class="string">&quot;headerimg&quot;</span><span class="attr">src</span>=<span class="string">&quot;https://npm.elemecdn.com/cover_img/msg/U5bb04af32be544c4b41206d9a42fcacfd.webp&quot;</span>/&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;padding: 5px 20px;&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">center</span>&gt;</span><span class="tag">&lt;<span class="name">h3</span> <span class="attr">calss</span>=<span class="string">&quot;title3&quot;</span>&gt;</span>来自小嘉的留言:<span class="tag">&lt;/<span class="name">h3</span>&gt;</span><span class="tag">&lt;/<span class="name">center</span>&gt;</span><span class="tag">&lt;<span class="name">center</span> <span class="attr">class</span>=<span class="string">&quot;comments&quot;</span>&gt;</span>有什么想问的？<span class="tag">&lt;<span class="name">br</span>&gt;</span>有什么想说的？<span class="tag">&lt;<span class="name">br</span>&gt;</span>有什么想吐槽的？<span class="tag">&lt;<span class="name">br</span>&gt;</span><span class="tag">&lt;/<span class="name">center</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;bottomcontent&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">class</span>=<span class="string">&quot;bottomimg&quot;</span><span class="attr">src</span>=<span class="string">&quot;https://npm.elemecdn.com/cover_img/msg/U0968ee80fd5c4f05a02bdda9709b041eE.webp&quot;</span>/&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;bottomhr&quot;</span>&gt;</span>自动书记人偶竭诚为您服务！<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">form</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">id</span>=<span class="string">&quot;afterimg&quot;</span><span class="attr">src</span>=<span class="string">&quot;https://npm.elemecdn.com/cover_img/msg/after.webp&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;mobile&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">form</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;formmain&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">class</span>=<span class="string">&quot;headerimg&quot;</span><span class="attr">src</span>=<span class="string">&quot;https://npm.elemecdn.com/cover_img/msg/U5bb04af32be544c4b41206d9a42fcacfd.webp&quot;</span>/&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;padding: 5px 20px;&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">center</span>&gt;</span><span class="tag">&lt;<span class="name">h3</span> <span class="attr">class</span>=<span class="string">&quot;title3&quot;</span>&gt;</span>来自小嘉的留言:<span class="tag">&lt;/<span class="name">h3</span>&gt;</span><span class="tag">&lt;/<span class="name">center</span>&gt;</span><span class="tag">&lt;<span class="name">center</span> <span class="attr">class</span>=<span class="string">&quot;comments&quot;</span>&gt;</span>有什么想问的？<span class="tag">&lt;<span class="name">br</span>&gt;</span>有什么想说的？<span class="tag">&lt;<span class="name">br</span>&gt;</span>有什么想吐槽的？<span class="tag">&lt;<span class="name">br</span>&gt;</span><span class="tag">&lt;/<span class="name">center</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;bottomcontent&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://npm.elemecdn.com/cover_img/msg/U0968ee80fd5c4f05a02bdda9709b041eE.webp&quot;</span><span class="attr">class</span>=<span class="string">&quot;bottomhr&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;bottomhr&quot;</span>&quot;&gt;</span>自动书记人偶竭诚为您服务！<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">form</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><p>然后按照自己的需求，该改的改</p><div class="note warning flat"><p>注：如果你是用 Typora 写作的话，粘贴时请用 <kbd>CTRL</kbd> + <kbd>SHIFT</kbd> + <kbd>V</kbd></p></div></div><div class="tab-item-content active" id="test2-2"><p>新版使用的是 npm 插件的方式，作者：<a href="https://akilar.top/">Akilar</a></p><p>在站点根目录执行</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-butterfly-envelope --save</span><br></pre></td></tr></table></figure><p>安装完成之后打开站点的配置文件或主题的配置文件，添加如下配置</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">envelope_comment:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">cover:</span> <span class="string">https://ae01.alicdn.com/kf/U5bb04af32be544c4b41206d9a42fcacfd.jpg</span> <span class="comment"># 信笺封面图</span></span><br><span class="line">  <span class="attr">message:</span>  <span class="comment"># 信笺内容，支持多行</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">有什么想问的？</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">有什么想说的？</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">有什么想吐槽的？</span></span><br><span class="line">  <span class="attr">bottom:</span> <span class="string">自动书记人偶竭诚为您服务！</span>   <span class="comment"># 信笺结束语，只能单行</span></span><br><span class="line">  <span class="attr">height:</span>                          <span class="comment"># 调整信笺划出高度，默认1050px</span></span><br><span class="line">  <span class="attr">path:</span>                            <span class="comment"># 【可选】comments 的路径名称。默认为 comments ， 生成的页面为 comments/index.html</span></span><br><span class="line">  <span class="attr">front_matter:</span>                    <span class="comment"># 【可选】comments页面的 front_matter 配置</span></span><br><span class="line">    <span class="attr">title:</span> <span class="string">留言板</span></span><br><span class="line">    <span class="attr">comments:</span> <span class="literal">false</span></span><br><span class="line">    <span class="attr">aside:</span> <span class="literal">false</span></span><br></pre></td></tr></table></figure><p>最后 hexo 三连</p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="gulp-压缩"><a href="#gulp-压缩" class="headerlink" title="gulp 压缩"></a>gulp 压缩</h2><details class="folding-tag" green><summary> 查看预览 </summary>              <div class='content'>              <p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/40c69f07ffd489cc7f075e647a8aeedf.webp" alt="img"></p>              </div>            </details><details class="folding-tag" green><summary> 配置 </summary>              <div class='content'>              <p>一个可以自动压缩 HTML、JS、CSS 文件、图片，可以将 ES6 语法转换成 ES5，减少网络请求，同时降低网络负担</p><p>首先全局安装 gulp</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --global gulp-cli</span><br></pre></td></tr></table></figure><p>安装压缩 HTML</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install gulp-htmlclean --save-dev</span><br><span class="line">npm install --save gulp-html-minifier-terser</span><br></pre></td></tr></table></figure><p>安装压缩 CSS</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install gulp-clean-css --save-dev</span><br></pre></td></tr></table></figure><p>安装压缩 JS</p><p>这里我选择 gulp-uglify + gulp-babel，可以把 ES6 转换成 ES5，因为兼容所以选择</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev gulp-uglify</span><br><span class="line">npm install --save-dev gulp-babel @babel/core @babel/preset-env</span><br></pre></td></tr></table></figure><p>安装如上插件之后，在你的博客根目录创建一个 <code>gulpfile.js</code> 文件并把如下代码 <code>CV</code> 进去</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> gulp = <span class="built_in">require</span>(<span class="string">&#x27;gulp&#x27;</span>);</span><br><span class="line"><span class="keyword">var</span> cleanCSS = <span class="built_in">require</span>(<span class="string">&#x27;gulp-clean-css&#x27;</span>);</span><br><span class="line"><span class="keyword">var</span> htmlmin = <span class="built_in">require</span>(<span class="string">&#x27;gulp-html-minifier-terser&#x27;</span>);</span><br><span class="line"><span class="keyword">var</span> htmlclean = <span class="built_in">require</span>(<span class="string">&#x27;gulp-htmlclean&#x27;</span>);</span><br><span class="line"><span class="keyword">var</span> uglify = <span class="built_in">require</span>(<span class="string">&#x27;gulp-uglify&#x27;</span>)</span><br><span class="line"><span class="keyword">var</span> babel = <span class="built_in">require</span>(<span class="string">&#x27;gulp-babel&#x27;</span>)</span><br><span class="line"><span class="comment">// 压缩js</span></span><br><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&#x27;compress&#x27;</span>, <span class="function">() =&gt;</span></span><br><span class="line">  gulp.<span class="title function_">src</span>([<span class="string">&#x27;./public/**/*.js&#x27;</span>, <span class="string">&#x27;!./public/**/*.min.js&#x27;</span>])</span><br><span class="line">    .<span class="title function_">pipe</span>(<span class="title function_">babel</span>(&#123;</span><br><span class="line">      <span class="attr">presets</span>: [<span class="string">&#x27;@babel/preset-env&#x27;</span>]</span><br><span class="line">    &#125;))</span><br><span class="line">    .<span class="title function_">pipe</span>(<span class="title function_">uglify</span>().<span class="title function_">on</span>(<span class="string">&#x27;error&#x27;</span>, <span class="keyword">function</span> (<span class="params">e</span>) &#123;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(e)</span><br><span class="line">    &#125;))</span><br><span class="line">    .<span class="title function_">pipe</span>(gulp.<span class="title function_">dest</span>(<span class="string">&#x27;./public&#x27;</span>))</span><br><span class="line">)</span><br><span class="line"><span class="comment">// 压缩css</span></span><br><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&#x27;minify-css&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> gulp.<span class="title function_">src</span>([<span class="string">&#x27;./public/**/*.css&#x27;</span>])</span><br><span class="line">        .<span class="title function_">pipe</span>(<span class="title function_">cleanCSS</span>(&#123;</span><br><span class="line">            <span class="attr">compatibility</span>: <span class="string">&#x27;ie11&#x27;</span></span><br><span class="line">        &#125;))</span><br><span class="line">        .<span class="title function_">pipe</span>(gulp.<span class="title function_">dest</span>(<span class="string">&#x27;./public&#x27;</span>));</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 压缩html</span></span><br><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&#x27;minify-html&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> gulp.<span class="title function_">src</span>(<span class="string">&#x27;./public/**/*.html&#x27;</span>)</span><br><span class="line">        .<span class="title function_">pipe</span>(<span class="title function_">htmlclean</span>())</span><br><span class="line">        .<span class="title function_">pipe</span>(<span class="title function_">htmlmin</span>(&#123;</span><br><span class="line">            <span class="attr">removeComments</span>: <span class="literal">true</span>,   <span class="comment">// 清除 html 注释</span></span><br><span class="line">            <span class="attr">collapseWhitespace</span>: <span class="literal">true</span>, <span class="comment">// 压缩 html</span></span><br><span class="line">            <span class="attr">collapseBooleanAttributes</span>: <span class="literal">true</span>,</span><br><span class="line">            <span class="comment">// 省略布尔属性的值，例如：&lt;input checked=&quot;true&quot;/&gt; ==&gt; &lt;input /&gt;</span></span><br><span class="line">            <span class="attr">removeEmptyAttributes</span>: <span class="literal">true</span>,</span><br><span class="line">            <span class="comment">// 删除所有空格作属性值，例如：&lt;input id=&quot;&quot; /&gt; ==&gt; &lt;input /&gt;</span></span><br><span class="line">            <span class="attr">removeScriptTypeAttributes</span>: <span class="literal">true</span>,</span><br><span class="line">            <span class="comment">// 删除&lt;script&gt;的type=&quot;text/javascript&quot;</span></span><br><span class="line">            <span class="attr">removeStyleLinkTypeAttributes</span>: <span class="literal">true</span>,</span><br><span class="line">            <span class="comment">// 删除&lt;style&gt;和&lt;link&gt;的 type=&quot;text/css&quot;</span></span><br><span class="line">            <span class="attr">minifyJS</span>: <span class="literal">true</span>, <span class="comment">// 压缩页面 JS</span></span><br><span class="line">            <span class="attr">minifyCSS</span>: <span class="literal">true</span>, <span class="comment">// 压缩页面 CSS</span></span><br><span class="line">            <span class="attr">minifyURLs</span>: <span class="literal">true</span> <span class="comment">// 压缩页面 URL</span></span><br><span class="line">        &#125;))</span><br><span class="line">        .<span class="title function_">pipe</span>(gulp.<span class="title function_">dest</span>(<span class="string">&#x27;./public&#x27;</span>))</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 运行gulp命令时依次执行以下任务</span></span><br><span class="line">gulp.<span class="title function_">task</span>(<span class="string">&#x27;default&#x27;</span>, gulp.<span class="title function_">parallel</span>(</span><br><span class="line">  <span class="string">&#x27;compress&#x27;</span>, <span class="string">&#x27;minify-css&#x27;</span>, <span class="string">&#x27;minify-html&#x27;</span></span><br><span class="line">))</span><br></pre></td></tr></table></figure><p><strong>使用：</strong></p><p>在 hexo g 之后运行 gulp 即可</p><p>例如：</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo cl &amp;&amp; hexo g &amp;&amp; gulp &amp;&amp; hexo d</span><br></pre></td></tr></table></figure><div class="note warning flat"><p>不过要注意的是，gulp 在本地运行是没有效果的，请部署之后再看效果 </p></div><p><strong>图片压缩</strong></p><p>图片压缩我用的是 Imagine</p><div class="btns rounded grid5">            <a class="button" href='https://github.com/meowtec/Imagine/releases' title='下载地址'><i class='fas fa-download'></i>下载地址</a>          </div><p>根据自己系统选择下载。</p><p>使用也很简单，下载安装之后，把想压缩的图片拖进去就好</p>              </div>            </details><h2 id="外挂标签"><a href="#外挂标签" class="headerlink" title="外挂标签"></a>外挂标签</h2><div class="note success flat"><p>关于外挂标签请移步至 Akilar 的 <a href="https://akilar.top/posts/615e2dec/">基于 Butterfly 的外挂标签引入</a> </p></div><div class="note success flat"><p>此时，您的部落格整体样貌就基本和我的差不多了 </p></div><h2 id="友链魔改"><a href="#友链魔改" class="headerlink" title="友链魔改"></a>友链魔改</h2><details class="folding-tag" green><summary> 查看预览 </summary>              <div class='content'>              <p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/link.2r0bbfmnqcu0.gif" alt="link"></p>              </div>            </details><details class="folding-tag" green><summary> 配置 </summary>              <div class='content'>              <p>原教程：<a href="https://akilar.top/posts/57291286/">Friend Link Card Beautify</a></p><p>友链这块修改了主题源码，是否要修改自行斟酌</p><p>魔改适用 <code>Butterfly@3.6.0 +</code></p><p><code>3.3.0-3.5.1</code> 的请看 Akilar 的原帖：<a href="https://akilar.top/posts/57291286/">Friend Link Card Beautify</a></p><ol><li><p>修改 <code>butterfly\layout\includes\page\flink.pug</code></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line">#article-container</span><br><span class="line">  <span class="keyword">if</span> top_img === <span class="literal">false</span></span><br><span class="line">    h1.<span class="property">page</span>-title= page.<span class="property">title</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (theme.<span class="property">flink_style</span> === <span class="string">&#x27;butterfly&#x27;</span>)</span><br><span class="line">    .<span class="property">flink</span></span><br><span class="line">      <span class="keyword">if</span> site.<span class="property">data</span>.<span class="property">link</span></span><br><span class="line">        each i <span class="keyword">in</span> site.<span class="property">data</span>.<span class="property">link</span></span><br><span class="line">          <span class="keyword">if</span> i.<span class="property">class_name</span></span><br><span class="line">            h2!= i.<span class="property">class_name</span></span><br><span class="line">          <span class="keyword">if</span> i.<span class="property">class_desc</span></span><br><span class="line">            .<span class="property">flink</span>-desc!=i.<span class="property">class_desc</span></span><br><span class="line">          .<span class="property">flink</span>-list</span><br><span class="line">            each item <span class="keyword">in</span> i.<span class="property">link_list</span></span><br><span class="line">              .<span class="property">flink</span>-list-item</span><br><span class="line">                <span class="title function_">a</span>(href=<span class="title function_">url_for</span>(item.<span class="property">link</span>)  title=item.<span class="property">name</span> target=<span class="string">&quot;_blank&quot;</span>)</span><br><span class="line">                  <span class="keyword">if</span> theme.<span class="property">lazyload</span>.<span class="property">enable</span></span><br><span class="line">                    <span class="title function_">img</span>(data-lazy-src=<span class="title function_">url_for</span>(item.<span class="property">avatar</span>) onerror=<span class="string">`this.onerror=null;this.src=&#x27;`</span> + <span class="title function_">url_for</span>(theme.<span class="property">error_img</span>.<span class="property">flink</span>) + <span class="string">`&#x27;`</span> alt=item.<span class="property">name</span> )</span><br><span class="line">                  <span class="keyword">else</span></span><br><span class="line">                    <span class="title function_">img</span>(src=<span class="title function_">url_for</span>(item.<span class="property">avatar</span>) onerror=<span class="string">`this.onerror=null;this.src=&#x27;`</span> + <span class="title function_">url_for</span>(theme.<span class="property">error_img</span>.<span class="property">flink</span>) + <span class="string">`&#x27;`</span> alt=item.<span class="property">name</span> )</span><br><span class="line">                  span.<span class="property">flink</span>-item-name= item.<span class="property">name</span></span><br><span class="line">                  span.<span class="property">flink</span>-item-<span class="title function_">desc</span>(title=item.<span class="property">descr</span>)= item.<span class="property">descr</span></span><br><span class="line">      != page.<span class="property">content</span></span><br><span class="line">  <span class="keyword">else</span> <span class="keyword">if</span> (theme.<span class="property">flink_style</span> === <span class="string">&#x27;volantis&#x27;</span>)</span><br><span class="line">    .<span class="property">flink</span></span><br><span class="line">      <span class="keyword">if</span> site.<span class="property">data</span>.<span class="property">link</span></span><br><span class="line">        each i <span class="keyword">in</span> site.<span class="property">data</span>.<span class="property">link</span></span><br><span class="line">          <span class="keyword">if</span> i.<span class="property">class_name</span></span><br><span class="line">            h2!= i.<span class="property">class_name</span></span><br><span class="line">          <span class="keyword">if</span> i.<span class="property">class_desc</span></span><br><span class="line">            .<span class="property">flink</span>-desc!=i.<span class="property">class_desc</span></span><br><span class="line">          .<span class="property">site</span>-card-group</span><br><span class="line">            each item <span class="keyword">in</span> i.<span class="property">link_list</span></span><br><span class="line">              a.<span class="property">site</span>-<span class="title function_">card</span>(target=<span class="string">&#x27;_blank&#x27;</span> rel=<span class="string">&#x27;noopener&#x27;</span> href=<span class="title function_">url_for</span>(item.<span class="property">link</span>))</span><br><span class="line">                .<span class="property">img</span></span><br><span class="line">                  - <span class="keyword">var</span> siteshot = item.<span class="property">siteshot</span> ? <span class="title function_">url_for</span>(item.<span class="property">siteshot</span>) : <span class="string">&#x27;https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/&#x27;</span> + item.<span class="property">link</span></span><br><span class="line">                  <span class="keyword">if</span> theme.<span class="property">lazyload</span>.<span class="property">enable</span></span><br><span class="line">                    <span class="title function_">img</span>(data-lazy-src=siteshot onerror=<span class="string">`this.onerror=null;this.src=&#x27;`</span> + <span class="title function_">url_for</span>(theme.<span class="property">error_img</span>.<span class="property">post_page</span>) + <span class="string">`&#x27;`</span> alt=<span class="string">&#x27;&#x27;</span> )</span><br><span class="line">                  <span class="keyword">else</span></span><br><span class="line">                    <span class="title function_">img</span>(src=siteshot onerror=<span class="string">`this.onerror=null;this.src=&#x27;`</span> + <span class="title function_">url_for</span>(theme.<span class="property">error_img</span>.<span class="property">flink</span>) + <span class="string">`&#x27;`</span> alt=<span class="string">&#x27;&#x27;</span> )</span><br><span class="line">                .<span class="property">info</span></span><br><span class="line">                  <span class="keyword">if</span> theme.<span class="property">lazyload</span>.<span class="property">enable</span></span><br><span class="line">                    <span class="title function_">img</span>(data-lazy-src=<span class="title function_">url_for</span>(item.<span class="property">avatar</span>) onerror=<span class="string">`this.onerror=null;this.src=&#x27;`</span> + <span class="title function_">url_for</span>(theme.<span class="property">error_img</span>.<span class="property">flink</span>) + <span class="string">`&#x27;`</span> alt=<span class="string">&#x27;&#x27;</span> )</span><br><span class="line">                  <span class="keyword">else</span></span><br><span class="line">                    <span class="title function_">img</span>(src=<span class="title function_">url_for</span>(item.<span class="property">avatar</span>) onerror=<span class="string">`this.onerror=null;this.src=&#x27;`</span> + <span class="title function_">url_for</span>(theme.<span class="property">error_img</span>.<span class="property">flink</span>) + <span class="string">`&#x27;`</span> alt=<span class="string">&#x27;&#x27;</span> )</span><br><span class="line">                  span.<span class="property">title</span>= item.<span class="property">name</span></span><br><span class="line">                  span.<span class="title function_">desc</span>(title=item.<span class="property">descr</span>)= item.<span class="property">descr</span></span><br><span class="line">      != page.<span class="property">content</span></span><br><span class="line">  <span class="keyword">else</span> <span class="keyword">if</span> (theme.<span class="property">flink_style</span> === <span class="string">&#x27;flexcard&#x27;</span>)</span><br><span class="line">    .<span class="property">flink</span></span><br><span class="line">      <span class="keyword">if</span> site.<span class="property">data</span>.<span class="property">link</span></span><br><span class="line">        each i <span class="keyword">in</span> site.<span class="property">data</span>.<span class="property">link</span></span><br><span class="line">          <span class="keyword">if</span> i.<span class="property">class_name</span></span><br><span class="line">            h2!= i.<span class="property">class_name</span></span><br><span class="line">          <span class="keyword">if</span> i.<span class="property">class_desc</span></span><br><span class="line">            .<span class="property">flink</span>-desc!=i.<span class="property">class_desc</span></span><br><span class="line">          .<span class="property">flink</span>-list</span><br><span class="line">            each item <span class="keyword">in</span> i.<span class="property">link_list</span></span><br><span class="line">              a.<span class="property">flink</span>-list-<span class="title function_">card</span>(href=<span class="title function_">url_for</span>(item.<span class="property">link</span>) target=<span class="string">&#x27;_blank&#x27;</span> data-title=item.<span class="property">descr</span>)</span><br><span class="line">                .<span class="property">wrapper</span>.<span class="property">cover</span></span><br><span class="line">                  - <span class="keyword">var</span> siteshot = item.<span class="property">siteshot</span> ? <span class="title function_">url_for</span>(item.<span class="property">siteshot</span>) : <span class="string">&#x27;https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/&#x27;</span> + item.<span class="property">link</span></span><br><span class="line">                  <span class="keyword">if</span> theme.<span class="property">lazyload</span>.<span class="property">enable</span></span><br><span class="line">                    img.<span class="property">cover</span>.<span class="title function_">fadeIn</span>(data-lazy-src=siteshot onerror=<span class="string">`this.onerror=null;this.src=&#x27;`</span> + <span class="title function_">url_for</span>(theme.<span class="property">error_img</span>.<span class="property">post_page</span>) + <span class="string">`&#x27;`</span> alt=<span class="string">&#x27;&#x27;</span> )</span><br><span class="line">                  <span class="keyword">else</span></span><br><span class="line">                    img.<span class="property">cover</span>.<span class="title function_">fadeIn</span>(src=siteshot onerror=<span class="string">`this.onerror=null;this.src=&#x27;`</span> + <span class="title function_">url_for</span>(theme.<span class="property">error_img</span>.<span class="property">flink</span>) + <span class="string">`&#x27;`</span> alt=<span class="string">&#x27;&#x27;</span> )    </span><br><span class="line">                .<span class="property">info</span></span><br><span class="line">                  <span class="keyword">if</span> theme.<span class="property">lazyload</span>.<span class="property">enable</span></span><br><span class="line">                    img.<span class="property">flink</span>-<span class="title function_">avatar</span>(data-lazy-src=<span class="title function_">url_for</span>(item.<span class="property">avatar</span>) onerror=<span class="string">`this.onerror=null;this.src=&#x27;`</span> + <span class="title function_">url_for</span>(theme.<span class="property">error_img</span>.<span class="property">flink</span>) + <span class="string">`&#x27;`</span> alt=<span class="string">&#x27;&#x27;</span> )</span><br><span class="line">                  <span class="keyword">else</span></span><br><span class="line">                    <span class="title function_">img</span>(src=<span class="title function_">url_for</span>(item.<span class="property">avatar</span>) onerror=<span class="string">`this.onerror=null;this.src=&#x27;`</span> + <span class="title function_">url_for</span>(theme.<span class="property">error_img</span>.<span class="property">flink</span>) + <span class="string">`&#x27;`</span> alt=<span class="string">&#x27;&#x27;</span> )</span><br><span class="line">                  span.<span class="property">flink</span>-sitename= item.<span class="property">name</span></span><br><span class="line">      != page.<span class="property">content</span></span><br></pre></td></tr></table></figure></li><li><p>修改 <code>butterfly\source\css\_page\flink.styl</code></p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> <span class="built_in">hexo-config</span>(<span class="string">&#x27;flink_style&#x27;</span>) == <span class="string">&#x27;butterfly&#x27;</span></span><br><span class="line">  .flink<span class="selector-id">#article-container</span></span><br><span class="line">    <span class="selector-class">.flink-desc</span></span><br><span class="line">      <span class="attribute">margin</span>: .<span class="number">2rem</span> <span class="number">0</span> .<span class="number">5rem</span></span><br><span class="line"></span><br><span class="line">    <span class="selector-class">.flink-list</span></span><br><span class="line">      <span class="attribute">overflow</span>: auto</span><br><span class="line">      <span class="attribute">padding</span>: <span class="number">10px</span> <span class="number">10px</span> <span class="number">0</span></span><br><span class="line">      <span class="attribute">text-align</span>: center</span><br><span class="line"></span><br><span class="line">      &amp; &gt; <span class="selector-class">.flink-list-item</span></span><br><span class="line">        <span class="attribute">position</span>: relative</span><br><span class="line">        <span class="attribute">float</span>: left</span><br><span class="line">        <span class="attribute">overflow</span>: hidden</span><br><span class="line">        <span class="attribute">margin</span>: <span class="number">15px</span> <span class="number">7px</span></span><br><span class="line">        <span class="attribute">width</span>: <span class="built_in">calc</span>(<span class="number">100%</span> / <span class="number">3</span> - <span class="number">15px</span>)</span><br><span class="line">        <span class="attribute">height</span>: <span class="number">90px</span></span><br><span class="line">        <span class="attribute">border-radius</span>: <span class="number">8px</span></span><br><span class="line">        <span class="attribute">line-height</span>: <span class="number">17px</span></span><br><span class="line">        -webkit-<span class="attribute">transform</span>: <span class="built_in">translateZ</span>(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        +<span class="built_in">maxWidth1024</span>()</span><br><span class="line">          <span class="attribute">width</span>: <span class="built_in">calc</span>(<span class="number">50%</span> - <span class="number">15px</span>) <span class="meta">!important</span></span><br><span class="line"></span><br><span class="line">        +<span class="built_in">maxWidth600</span>()</span><br><span class="line">          <span class="attribute">width</span>: <span class="built_in">calc</span>(<span class="number">100%</span> - <span class="number">15px</span>) <span class="meta">!important</span></span><br><span class="line"></span><br><span class="line">        <span class="selector-pseudo">&amp;:hover</span></span><br><span class="line">          <span class="selector-tag">img</span></span><br><span class="line">            <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">360deg</span>)</span><br><span class="line"></span><br><span class="line">        <span class="selector-pseudo">&amp;:before</span></span><br><span class="line">          <span class="attribute">position</span>: absolute</span><br><span class="line">          <span class="attribute">top</span>: <span class="number">0</span></span><br><span class="line">          <span class="attribute">right</span>: <span class="number">0</span></span><br><span class="line">          <span class="attribute">bottom</span>: <span class="number">0</span></span><br><span class="line">          <span class="attribute">left</span>: <span class="number">0</span></span><br><span class="line">          <span class="attribute">z-index</span>: -<span class="number">1</span></span><br><span class="line">          <span class="attribute">background</span>: <span class="built_in">var</span>(--text-bg-hover)</span><br><span class="line">          <span class="attribute">content</span>: <span class="string">&#x27;&#x27;</span></span><br><span class="line">          <span class="attribute">transition</span>: transform .<span class="number">3s</span> ease-out</span><br><span class="line">          <span class="attribute">transform</span>: <span class="built_in">scale</span>(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">        <span class="selector-pseudo">&amp;:hover</span><span class="selector-pseudo">:before</span>,</span><br><span class="line">        <span class="selector-pseudo">&amp;:focus</span><span class="selector-pseudo">:before</span>,</span><br><span class="line">        <span class="selector-pseudo">&amp;:active</span><span class="selector-pseudo">:before</span></span><br><span class="line">          <span class="attribute">transform</span>: <span class="built_in">scale</span>(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">        <span class="selector-tag">a</span></span><br><span class="line">          <span class="attribute">color</span>: <span class="built_in">var</span>(--font-color)</span><br><span class="line">          <span class="attribute">text-decoration</span>: none</span><br><span class="line"></span><br><span class="line">          <span class="selector-tag">img</span></span><br><span class="line">            <span class="attribute">float</span>: left</span><br><span class="line">            <span class="attribute">margin</span>: <span class="number">15px</span> <span class="number">10px</span></span><br><span class="line">            <span class="attribute">width</span>: <span class="number">60px</span></span><br><span class="line">            <span class="attribute">height</span>: <span class="number">60px</span></span><br><span class="line">            <span class="attribute">border-radius</span>: <span class="number">35px</span></span><br><span class="line">            <span class="attribute">transition</span>: all .<span class="number">3s</span></span><br><span class="line"></span><br><span class="line">          <span class="selector-class">.img-alt</span></span><br><span class="line">            <span class="attribute">display</span>: none</span><br><span class="line"></span><br><span class="line">          <span class="selector-class">.flink-item-name</span></span><br><span class="line">            <span class="keyword">@extend</span> <span class="selector-class">.limit-one-line</span></span><br><span class="line">            <span class="attribute">display</span>: block</span><br><span class="line">            <span class="attribute">padding</span>: <span class="number">16px</span> <span class="number">10px</span> <span class="number">0</span> <span class="number">0</span></span><br><span class="line">            <span class="attribute">height</span>: <span class="number">40px</span></span><br><span class="line">            <span class="attribute">font-weight</span>: bold</span><br><span class="line">            <span class="attribute">font-size</span>: <span class="number">1.43em</span></span><br><span class="line"></span><br><span class="line">          <span class="selector-class">.flink-item-desc</span></span><br><span class="line">            <span class="keyword">@extend</span> <span class="selector-class">.limit-one-line</span></span><br><span class="line">            <span class="attribute">display</span>: block</span><br><span class="line">            <span class="attribute">padding</span>: <span class="number">16px</span> <span class="number">10px</span> <span class="number">16px</span> <span class="number">0</span></span><br><span class="line">            <span class="attribute">height</span>: <span class="number">50px</span></span><br><span class="line">            <span class="attribute">font-size</span>: .<span class="number">93em</span></span><br><span class="line"><span class="keyword">else</span> <span class="keyword">if</span> <span class="built_in">hexo-config</span>(<span class="string">&#x27;flink_style&#x27;</span>) == <span class="string">&#x27;volantis&#x27;</span></span><br><span class="line">  <span class="built_in">trans</span>(<span class="variable">$time</span> = <span class="number">0.28s</span>)</span><br><span class="line">    <span class="attribute">transition</span>: all <span class="variable">$time</span> ease</span><br><span class="line">    -moz-<span class="attribute">transition</span>: all <span class="variable">$time</span> ease</span><br><span class="line">    -webkit-<span class="attribute">transition</span>: all <span class="variable">$time</span> ease</span><br><span class="line">    -o-<span class="attribute">transition</span>: all <span class="variable">$time</span> ease</span><br><span class="line">  <span class="selector-class">.site-card-group</span></span><br><span class="line">    <span class="attribute">display</span>: flex</span><br><span class="line">    <span class="attribute">flex-wrap</span>: wrap</span><br><span class="line">    <span class="attribute">justify-content</span>: flex-start</span><br><span class="line">    <span class="attribute">margin</span>: -<span class="number">0.5</span> * <span class="number">16px</span></span><br><span class="line">    <span class="attribute">align-items</span>: stretch</span><br><span class="line">  <span class="selector-class">.site-card</span></span><br><span class="line">    <span class="attribute">margin</span>: <span class="number">16px</span> * <span class="number">0.5</span></span><br><span class="line">    <span class="attribute">width</span>: <span class="string">&quot;calc(100% / 4 - %s)&quot;</span> % <span class="number">16px</span></span><br><span class="line">    <span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">2048px</span>)</span><br><span class="line">        <span class="attribute">width</span>: &quot;calc(<span class="number">100%</span> / <span class="number">5</span> - %s)&quot; % <span class="number">16px</span></span><br><span class="line">    @media screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">768px</span>)</span><br><span class="line">        <span class="attribute">width</span>: &quot;calc(<span class="number">100%</span> / <span class="number">3</span> - %s)&quot; % <span class="number">16px</span></span><br><span class="line">    @media screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">500px</span>)</span><br><span class="line">        <span class="attribute">width</span>: &quot;calc(<span class="number">100%</span> / <span class="number">2</span> - %s)&quot; % <span class="number">16px</span></span><br><span class="line">    display: block</span><br><span class="line">    line-height: <span class="number">1.4</span></span><br><span class="line">    <span class="attribute">height</span> <span class="number">100%</span></span><br><span class="line">    .img</span><br><span class="line">      <span class="attribute">width</span>: <span class="number">100%</span></span><br><span class="line">      <span class="attribute">height</span> <span class="number">120px</span></span><br><span class="line">      @media screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">500px</span>)</span><br><span class="line">        <span class="attribute">height</span> <span class="number">100px</span></span><br><span class="line">      overflow: hidden</span><br><span class="line">      border-radius: <span class="number">12px</span> * <span class="number">0.5</span></span><br><span class="line">      box-shadow: <span class="number">0</span> <span class="number">1px</span> <span class="number">2px</span> <span class="number">0px</span> rgba(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.2</span>)</span><br><span class="line">      background: #f6f6f6</span><br><span class="line">      img</span><br><span class="line">        <span class="attribute">width</span>: <span class="number">100%</span></span><br><span class="line">        <span class="attribute">height</span> <span class="number">100%</span></span><br><span class="line">        // trans(.<span class="number">75s</span>)</span><br><span class="line">        transition: transform <span class="number">2s</span> ease</span><br><span class="line">        object-fit: cover</span><br><span class="line"></span><br><span class="line">    .info</span><br><span class="line">      margin-top: <span class="number">16px</span> * <span class="number">0.5</span></span><br><span class="line">      img</span><br><span class="line">        <span class="attribute">width</span>: <span class="number">32px</span></span><br><span class="line">        <span class="attribute">height</span>: <span class="number">32px</span></span><br><span class="line">        border-radius: <span class="number">16px</span></span><br><span class="line">        float: left</span><br><span class="line">        margin-right: <span class="number">8px</span></span><br><span class="line">        margin-top: <span class="number">2px</span></span><br><span class="line">      span</span><br><span class="line">        display: block</span><br><span class="line">      .title</span><br><span class="line">        font-weight: <span class="number">600</span></span><br><span class="line">        font-size: $fontsize-list</span><br><span class="line">        <span class="attribute">color</span>: #<span class="number">444</span></span><br><span class="line">        display: -webkit-box</span><br><span class="line">        -webkit-box-orient: vertical</span><br><span class="line">        overflow: hidden</span><br><span class="line">        -webkit-line-clamp: <span class="number">1</span></span><br><span class="line">        trans()</span><br><span class="line">      .desc</span><br><span class="line">        font-size: $fontsize-footnote</span><br><span class="line">        word-wrap: break-word;</span><br><span class="line">        <span class="attribute">line-height</span>: <span class="number">1.2</span></span><br><span class="line">        <span class="attribute">color</span>: <span class="number">#888</span></span><br><span class="line">        <span class="attribute">display</span>: -webkit-box</span><br><span class="line">        -webkit-box-orient: vertical</span><br><span class="line">        <span class="attribute">overflow</span>: hidden</span><br><span class="line">        -webkit-line-clamp: <span class="number">2</span></span><br><span class="line">    <span class="selector-class">.img</span></span><br><span class="line">      <span class="built_in">trans</span>()</span><br><span class="line">    <span class="selector-pseudo">&amp;:hover</span></span><br><span class="line">      <span class="selector-class">.img</span></span><br><span class="line">        <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">4px</span> <span class="number">8px</span> <span class="number">0px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.1</span>), <span class="number">0</span> <span class="number">2px</span> <span class="number">4px</span> <span class="number">0px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.1</span>), <span class="number">0</span> <span class="number">4px</span> <span class="number">8px</span> <span class="number">0px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.1</span>), <span class="number">0</span> <span class="number">8px</span> <span class="number">16px</span> <span class="number">0px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.1</span>)</span><br><span class="line">      <span class="selector-class">.info</span> <span class="selector-class">.title</span></span><br><span class="line">        <span class="attribute">color</span>: <span class="number">#ff5722</span></span><br><span class="line"><span class="keyword">else</span> <span class="keyword">if</span> <span class="built_in">hexo-config</span>(<span class="string">&#x27;flink_style&#x27;</span>) == <span class="string">&#x27;flexcard&#x27;</span></span><br><span class="line">  <span class="selector-id">#article-container</span> <span class="selector-tag">img</span></span><br><span class="line">        <span class="attribute">margin</span> <span class="number">0</span> auto<span class="meta">!important</span></span><br><span class="line">  <span class="selector-class">.flink-list</span></span><br><span class="line">    <span class="attribute">overflow</span> auto</span><br><span class="line">    &amp; &gt; <span class="selector-tag">a</span></span><br><span class="line">      <span class="attribute">width</span> <span class="built_in">calc</span>(<span class="number">25%</span> - <span class="number">15px</span>)</span><br><span class="line">      <span class="attribute">height</span> <span class="number">130px</span></span><br><span class="line">      <span class="attribute">position</span> relative</span><br><span class="line">      <span class="attribute">display</span> block</span><br><span class="line">      <span class="attribute">margin</span> <span class="number">15px</span> <span class="number">7px</span></span><br><span class="line">      <span class="attribute">float</span> left</span><br><span class="line">      <span class="attribute">overflow</span> hidden</span><br><span class="line">      <span class="attribute">border-radius</span> <span class="number">10px</span></span><br><span class="line">      <span class="attribute">transition</span> all .<span class="number">3s</span> ease <span class="number">0s</span>, transform .<span class="number">6s</span> <span class="built_in">cubic-bezier</span>(.<span class="number">6</span>, .<span class="number">2</span>, .<span class="number">1</span>, <span class="number">1</span>) <span class="number">0s</span></span><br><span class="line">      <span class="attribute">box-shadow</span> <span class="number">0</span> <span class="number">14px</span> <span class="number">38px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, .<span class="number">08</span>), <span class="number">0</span> <span class="number">3px</span> <span class="number">8px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, .<span class="number">06</span>)</span><br><span class="line">      <span class="selector-pseudo">&amp;:hover</span></span><br><span class="line">        <span class="selector-class">.info</span></span><br><span class="line">          <span class="attribute">transform</span> <span class="built_in">translateY</span>(-<span class="number">100%</span>)</span><br><span class="line">        <span class="selector-class">.wrapper</span></span><br><span class="line">          <span class="selector-tag">img</span></span><br><span class="line">            <span class="attribute">transform</span> <span class="built_in">scale</span>(<span class="number">1.2</span>)</span><br><span class="line">        <span class="selector-pseudo">&amp;:before</span></span><br><span class="line">          <span class="attribute">position</span>: fixed</span><br><span class="line">          <span class="attribute">width</span>:inherit</span><br><span class="line">          <span class="attribute">margin</span>:auto</span><br><span class="line">          <span class="attribute">left</span>:<span class="number">0</span></span><br><span class="line">          <span class="attribute">right</span>:<span class="number">0</span></span><br><span class="line">          <span class="attribute">top</span>:<span class="number">10%</span></span><br><span class="line">          <span class="attribute">border-radius</span>: <span class="number">10px</span></span><br><span class="line">          <span class="attribute">text-align</span>: center</span><br><span class="line">          <span class="attribute">z-index</span>: <span class="number">100</span></span><br><span class="line">          <span class="attribute">content</span>: <span class="built_in">attr</span>(data-title)</span><br><span class="line">          <span class="attribute">font-size</span>: <span class="number">20px</span></span><br><span class="line">          <span class="attribute">color</span>: <span class="number">#fff</span></span><br><span class="line">          <span class="attribute">padding</span>: <span class="number">10px</span></span><br><span class="line">          <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(<span class="variable">$theme</span>-color,<span class="number">0.8</span>)</span><br><span class="line">      <span class="selector-class">.cover</span></span><br><span class="line">        <span class="attribute">width</span> <span class="number">100%</span></span><br><span class="line">        <span class="attribute">transition</span> transform .<span class="number">5s</span> ease-out</span><br><span class="line">      <span class="selector-class">.wrapper</span></span><br><span class="line">        <span class="attribute">position</span> relative</span><br><span class="line">        <span class="selector-class">.fadeIn</span></span><br><span class="line">          <span class="attribute">animation</span> coverIn .<span class="number">8s</span> ease-out forwards</span><br><span class="line">        <span class="selector-tag">img</span></span><br><span class="line">          <span class="attribute">height</span> <span class="number">130px</span></span><br><span class="line">          <span class="attribute">pointer-events</span> none</span><br><span class="line">      <span class="selector-class">.info</span></span><br><span class="line">        <span class="attribute">display</span> flex</span><br><span class="line">        <span class="attribute">flex-direction</span> column</span><br><span class="line">        <span class="attribute">justify-content</span> center</span><br><span class="line">        <span class="attribute">align-items</span> center</span><br><span class="line">        <span class="attribute">width</span> <span class="number">100%</span></span><br><span class="line">        <span class="attribute">height</span> <span class="number">100%</span></span><br><span class="line">        <span class="attribute">overflow</span> hidden</span><br><span class="line">        <span class="attribute">border-radius</span> <span class="number">3px</span></span><br><span class="line">        <span class="attribute">background-color</span> <span class="built_in">hsla</span>(<span class="number">0</span>, <span class="number">0%</span>, <span class="number">100%</span>, .<span class="number">7</span>)</span><br><span class="line">        <span class="attribute">transition</span> transform .<span class="number">5s</span> <span class="built_in">cubic-bezier</span>(.<span class="number">6</span>, .<span class="number">2</span>, .<span class="number">1</span>, <span class="number">1</span>) <span class="number">0s</span></span><br><span class="line">        <span class="selector-tag">img</span></span><br><span class="line">          <span class="attribute">position</span> relative</span><br><span class="line">          <span class="attribute">top</span> <span class="number">22px</span> //因为字体大小不同，可能导致头像偏高，可以在此处通过修改top的值来微调头像框的位置至卡片正中。</span><br><span class="line">          <span class="attribute">width</span> <span class="number">66px</span></span><br><span class="line">          <span class="attribute">height</span> <span class="number">66px</span></span><br><span class="line">          <span class="attribute">border-radius</span> <span class="number">50%</span></span><br><span class="line">          <span class="attribute">box-shadow</span> <span class="number">0</span> <span class="number">0</span> <span class="number">10px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, .<span class="number">3</span>)</span><br><span class="line">          <span class="attribute">z-index</span> <span class="number">1</span></span><br><span class="line">          <span class="attribute">text-align</span> center</span><br><span class="line">          <span class="attribute">pointer-events</span> none</span><br><span class="line">        <span class="selector-tag">span</span></span><br><span class="line">          <span class="attribute">padding</span> <span class="number">20px</span> <span class="number">10%</span> <span class="number">60px</span> <span class="number">10%</span></span><br><span class="line">          <span class="attribute">font-size</span> <span class="number">16px</span></span><br><span class="line">          <span class="attribute">width</span> <span class="number">100%</span></span><br><span class="line">          <span class="attribute">text-align</span> center</span><br><span class="line">          <span class="attribute">box-shadow</span> <span class="number">0</span> <span class="number">0</span> <span class="number">10px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, .<span class="number">3</span>)</span><br><span class="line">          <span class="attribute">background-color</span> <span class="built_in">hsla</span>(<span class="number">0</span>, <span class="number">0%</span>, <span class="number">100%</span>, .<span class="number">7</span>)</span><br><span class="line">          <span class="attribute">color</span> <span class="built_in">var</span>(--font-color)</span><br><span class="line">          <span class="attribute">white-space</span> nowrap</span><br><span class="line">          <span class="attribute">overflow</span> hidden</span><br><span class="line">          <span class="attribute">text-overflow</span> ellipsis</span><br><span class="line">  .flink-list&gt;<span class="selector-tag">a</span> <span class="selector-class">.info</span>,</span><br><span class="line">  .flink-list&gt;<span class="selector-tag">a</span> <span class="selector-class">.wrapper</span> <span class="selector-class">.cover</span></span><br><span class="line">    <span class="attribute">position</span> absolute</span><br><span class="line">    <span class="attribute">top</span> <span class="number">0</span></span><br><span class="line">    <span class="attribute">left</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>:<span class="number">1024px</span>)</span><br><span class="line">    .flink-list</span><br><span class="line">      &amp; &gt; a</span><br><span class="line">        <span class="attribute">width</span> calc(<span class="number">33.33333%</span> - <span class="number">15px</span>)</span><br><span class="line"></span><br><span class="line">  @media screen <span class="keyword">and</span> (<span class="attribute">max-width</span>:<span class="number">600px</span>)</span><br><span class="line">    .flink-list</span><br><span class="line">      &amp; &gt; a</span><br><span class="line">        <span class="attribute">width</span> calc(<span class="number">50%</span> - <span class="number">15px</span>)</span><br><span class="line"></span><br><span class="line">  [data-theme=dark]</span><br><span class="line">    .flink-list a .info,</span><br><span class="line">    .flink-list a .info span</span><br><span class="line">      background-color rgba(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, .<span class="number">6</span>)</span><br><span class="line">    .flink-list</span><br><span class="line">      &amp; &gt; a</span><br><span class="line">        &amp;:<span class="attribute">hover</span></span><br><span class="line">          &amp;:before</span><br><span class="line">            background-color: rgba(#<span class="number">121212</span>,<span class="number">0.8</span>);</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p>在 <code>blog\source\_data\link.yml</code> 根据自身是否添加 <code>siteshot</code>，因为 Volantis 的 site-card 比 Butterfly 的 flink-card 多了一个站点缩略图，所以需要再额外添加一条 <code>siteshot</code> 配置项，不添加也可以，通过 <code>butterfly\layout\includes\page\flink.pug</code> 源码可以看出，如果你配置了 <code>siteshot</code> 的话，它就走 <code>siteshot</code>，没有配置的话，默认就调 <code>API</code>，其优先级 <code>siteshot</code> 高于 <code>API</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/flink.5wxtyvv4p1w0.webp" alt="flink.pug"></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> <span class="attr">class_name:</span> <span class="string">xxx</span></span><br><span class="line">  <span class="attr">class_desc:</span> <span class="string">xxx</span></span><br><span class="line">  <span class="attr">link_list:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">xxx</span></span><br><span class="line">      <span class="attr">link:</span> <span class="string">xxx</span></span><br><span class="line">      <span class="attr">avatar:</span> <span class="string">xxx</span></span><br><span class="line">      <span class="attr">descr:</span> <span class="string">xxx</span></span><br><span class="line">      <span class="attr">siteshot:</span>  <span class="comment"># 站点缩略图</span></span><br></pre></td></tr></table></figure></li><li><p>在 <code>blog\_config.butterfly.yml</code> 中添加配置项，如果你没有用主题升级方法的话，那么在 <code>butterfly\_config.yml</code> 中添加。</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 友链样式，butterfly 为默认样式，volantis 为站点卡片样式.flexcard 为弹性卡片样式</span></span><br><span class="line"><span class="attr">flink_style:</span> <span class="string">flexcard</span> <span class="comment"># butterfly | volantis | flexcard</span></span><br></pre></td></tr></table></figure><p>继续配置懒加载和 404 配置，因为站点卡片添加了懒加载和图片失效替换</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 替换无法显示的图片</span></span><br><span class="line"><span class="attr">error_img:</span></span><br><span class="line">  <span class="attr">flink:</span> <span class="string">//cdn.jsdelivr.net...</span>         <span class="comment"># 头像失效替换图</span></span><br><span class="line">  <span class="attr">post_page:</span> <span class="string">//cdn.jsdelivr.net...</span>     <span class="comment"># 文章图失效替换图</span></span><br></pre></td></tr></table></figure></li><li><p><code>hexo cl &amp;&amp; hexo g &amp;&amp; hexo s</code> 本地调式查看效果</p></li></ol><p><strong>已知问题</strong></p><p>相册样式错乱</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/link.5qewaz6nq2g0.webp" alt="link"></p><p><strong>解决：</strong></p><p>在你的自定义 <code>css</code> 文件中，添加如下代码</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">a</span> &gt; <span class="selector-tag">img</span>, <span class="selector-class">.justified-gallery</span> &gt; <span class="selector-tag">div</span> &gt; <span class="selector-tag">img</span>,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> &gt; <span class="selector-tag">figure</span> &gt; <span class="selector-tag">img</span>,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> &gt; <span class="selector-tag">a</span> &gt; <span class="selector-tag">a</span> &gt; <span class="selector-tag">img</span>,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> &gt; <span class="selector-tag">div</span> &gt; <span class="selector-tag">a</span> &gt; <span class="selector-tag">img</span>,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> &gt; <span class="selector-tag">figure</span> &gt; <span class="selector-tag">a</span> &gt; <span class="selector-tag">img</span>,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> &gt; <span class="selector-tag">a</span> &gt; svg,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> &gt; <span class="selector-tag">div</span> &gt; svg,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> &gt; <span class="selector-tag">figure</span> &gt; svg,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> &gt; <span class="selector-tag">a</span> &gt; <span class="selector-tag">a</span> &gt; svg,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> &gt; <span class="selector-tag">div</span> &gt; <span class="selector-tag">a</span> &gt; svg,</span><br><span class="line"><span class="selector-class">.justified-gallery</span> &gt; <span class="selector-tag">figure</span> &gt; <span class="selector-tag">a</span> &gt; svg&#123;</span><br><span class="line">  <span class="attribute">position</span>:static<span class="meta">!important</span>;&#125;</span><br></pre></td></tr></table></figure><p><strong>其它问题</strong></p><p>参考：<a href="https://akilar.top/posts/57291286/#%E5%8F%AF%E8%83%BD%E9%81%87%E5%88%B0%E7%9A%84Bug">可能遇到的 Bug</a></p>              </div>            </details><h2 id="友链朋友圈"><a href="#友链朋友圈" class="headerlink" title="友链朋友圈"></a>友链朋友圈</h2><p>参考：<a href="https://zfe.space/post/friend-link-circle.html">基于 hexo 的友链朋友圈</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/link_pyq.6ggkit8i9d00.webp" alt="link_pyq"></p><h2 id="GitHub-贡献度"><a href="#GitHub-贡献度" class="headerlink" title="GitHub 贡献度"></a>GitHub 贡献度</h2><details class="folding-tag" green><summary> 查看预览 </summary>              <div class='content'>              <p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/images.5wvv2ppeka80.webp" alt="images"></p>              </div>            </details><details class="folding-tag" green><summary> 配置 </summary>              <div class='content'>              <p>项目地址：<a href="https://github.com/Zfour/hexo-github-calendar">hexo-github-calendar</a></p><p>先安装插件</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i hexo-githubcalendar --save</span><br></pre></td></tr></table></figure><p>然后打开 Hexo 的配置文件，注：不是主题的配置文件</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">githubcalendar:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">enable_page:</span> <span class="string">/</span>  <span class="comment"># 表示只在根目录(首页)显示</span></span><br><span class="line">  <span class="attr">user:</span> <span class="string">zjwo</span>  <span class="comment"># 替换成你 GitHub 的用户名</span></span><br><span class="line">  <span class="attr">layout_id:</span> <span class="string">recent-posts</span></span><br><span class="line">  <span class="attr">githubcalendar_html:</span> <span class="string">&#x27;&lt;div class=&quot;recent-post-item&quot; style=&quot;width:100%;height:auto;padding:10px;&quot;&gt;&lt;div id=&quot;github_loading&quot; style=&quot;width:10%;height:100%;margin:0 auto;display: block&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;  viewBox=&quot;0 0 50 50&quot; style=&quot;enable-background:new 0 0 50 50&quot; xml:space=&quot;preserve&quot;&gt;&lt;path fill=&quot;#d0d0d0&quot; d=&quot;M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z&quot; transform=&quot;rotate(275.098 25 25)&quot;&gt;&lt;animateTransform attributeType=&quot;xml&quot; attributeName=&quot;transform&quot; type=&quot;rotate&quot; from=&quot;0 25 25&quot; to=&quot;360 25 25&quot; dur=&quot;0.6s&quot; repeatCount=&quot;indefinite&quot;&gt;&lt;/animateTransform&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;div id=&quot;github_container&quot;&gt;&lt;/div&gt;&lt;/div&gt;&#x27;</span></span><br><span class="line">  <span class="attr">pc_minheight:</span> <span class="string">280px</span></span><br><span class="line">  <span class="attr">mobile_minheight:</span> <span class="string">0px</span></span><br><span class="line">  <span class="attr">color:</span> <span class="string">&quot;[&#x27;#ebedf0&#x27;, &#x27;#fdcdec&#x27;, &#x27;#fc9bd9&#x27;, &#x27;#fa6ac5&#x27;, &#x27;#f838b2&#x27;, &#x27;#f5089f&#x27;, &#x27;#c4067e&#x27;, &#x27;#92055e&#x27;, &#x27;#540336&#x27;, &#x27;#48022f&#x27;, &#x27;#30021f&#x27;]&quot;</span></span><br><span class="line">  <span class="attr">api:</span> <span class="string">https://python-github-calendar-api.vercel.app/api</span></span><br><span class="line">  <span class="comment"># api: https://python-gitee-calendar-api.vercel.app/api</span></span><br><span class="line">  <span class="attr">calendar_js:</span> <span class="string">https://cdn.jsdelivr.net/gh/Zfour/hexo-github-calendar@1.16/hexo_githubcalendar.js</span></span><br></pre></td></tr></table></figure><p>如果你觉得默认的浅紫色不好看，可以选择以下色调</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 橘黄色调</span></span><br><span class="line"><span class="attr">color:</span> <span class="string">&quot;[&#x27;#e4dfd7&#x27;, &#x27;#f9f4dc&#x27;, &#x27;#f7e8aa&#x27;, &#x27;#f7e8aa&#x27;, &#x27;#f8df72&#x27;, &#x27;#fcd217&#x27;, &#x27;#fcc515&#x27;, &#x27;#f28e16&#x27;, &#x27;#fb8b05&#x27;, &#x27;#d85916&#x27;, &#x27;#f43e06&#x27;]&quot;</span></span><br><span class="line"><span class="comment"># 翠绿色调</span></span><br><span class="line"><span class="attr">color:</span> <span class="string">&quot;[&#x27;#ebedf0&#x27;, &#x27;#f0fff4&#x27;, &#x27;#dcffe4&#x27;, &#x27;#bef5cb&#x27;, &#x27;#85e89d&#x27;, &#x27;#34d058&#x27;, &#x27;#28a745&#x27;, &#x27;#22863a&#x27;, &#x27;#176f2c&#x27;, &#x27;#165c26&#x27;, &#x27;#144620&#x27;]&quot;</span></span><br><span class="line"><span class="comment"># 天青色调</span></span><br><span class="line"><span class="attr">color:</span> <span class="string">&quot;[&#x27;#ebedf0&#x27;, &#x27;#f1f8ff&#x27;, &#x27;#dbedff&#x27;, &#x27;#c8e1ff&#x27;, &#x27;#79b8ff&#x27;, &#x27;#2188ff&#x27;, &#x27;#0366d6&#x27;, &#x27;#005cc5&#x27;, &#x27;#044289&#x27;, &#x27;#032f62&#x27;, &#x27;#05264c&#x27;]&quot;</span></span><br></pre></td></tr></table></figure><p>也可以自己自定义</p><p>最后 <code>hexo cl</code> 三连命令查看效果</p>              </div>            </details><h2 id="说说配置"><a href="#说说配置" class="headerlink" title="说说配置"></a>说说配置</h2><div class="tabs" id="talk"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="talk-1">Artitalk</button><button type="button" class="tab " data-href="talk-2">哔哔</button></ul><div class="tab-contents"><div class="tab-item-content active" id="talk-1"><p><strong>前置要求</strong>，参考 <a href="https://artitalk.js.org/doc.html#%F0%9F%8C%88-leancloud-%E7%9A%84%E7%9B%B8%E5%85%B3%E5%87%86%E5%A4%87">Artitalk 文档 - LeanCloud 的相关准备</a>，必须要配置好 LeanCloud 再往下看</p><p>从 Butterfly@<a href="https://github.com/jerryc127/hexo-theme-butterfly/releases/tag/3.7.0">3.7.0</a> 开始，移除了 artitalk，改为 npm 安装的方式</p><p>在你的博客目录下安装插件</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-butterfly-artitalk</span><br></pre></td></tr></table></figure><p>然后手动在 butterfly 主题下的配置文件添加如下配置</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">artitalk:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">appId:</span></span><br><span class="line">  <span class="attr">appKey:</span></span><br><span class="line">  <span class="attr">path:</span></span><br><span class="line">  <span class="attr">js:</span></span><br><span class="line">  <span class="attr">option:</span></span><br><span class="line">  <span class="attr">front_matter:</span></span><br><span class="line">    <span class="attr">aside:</span> <span class="literal">false</span> <span class="comment"># 关闭侧边栏</span></span><br><span class="line">    <span class="attr">comments:</span> <span class="literal">false</span> <span class="comment"># 关闭评论</span></span><br></pre></td></tr></table></figure><table><thead><tr><th align="center">参数</th><th align="center">说明</th></tr></thead><tbody><tr><td align="center">appId</td><td align="center">【必须】LeanCloud 创建应用的 AppID</td></tr><tr><td align="center">appKey</td><td align="center">【必须】LeanCloud 创建应用的 AppKEY</td></tr><tr><td align="center">path</td><td align="center">【可选】Artitalk 的路径名称（默认为 <code>artitalk</code>，生成的页面为 artitalk/index.html）</td></tr><tr><td align="center">js</td><td align="center">【可选】更換 Artitalk 的 js CDN（默认为 <code>https://cdn.jsdelivr.net/npm/artitalk</code>）</td></tr><tr><td align="center">option</td><td align="center">【可选】Artitalk 需要的额外配置</td></tr><tr><td align="center">front_matter</td><td align="center">【可选】Artitalk 页面的 front_matter 配置</td></tr></tbody></table><p><strong>效果：</strong></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/artitalk.75829xmmrfc0.webp" alt="artitalk"></p><p class="div-border red">另外说明下，如果使用了 artitalk，无需额外创建页面，主题会根据配置自动生成页面！</p></div><div class="tab-item-content" id="talk-2"><p>使用前请先确保参考林木木的<a href="https://immmmm.com/bb-by-wechat-pro/#%E6%89%8B%E5%8A%A8%E9%83%A8%E7%BD%B2%E5%88%9B%E5%BB%BA%E5%BA%94%E7%94%A8">教程</a>成功配置好云函数之后再来使用</p><p>前端配置只需在你的哔哔页面的 <code>index.md</code> 复制如下代码并进行修改即可！</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&#x27;speak&#x27;</span>&gt;</span><span class="tag">&lt;/<span class="name">speak</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 使用markdown渲染 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">src</span>=<span class="string">&quot;https://npm.elemecdn.com/nanshen/js/blog/bb/ispeak-bber.min.js&quot;</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span> &gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 不使用markdown渲染 --&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- &lt;script type=&quot;text/javascript&quot; src=&quot;https://npm.elemecdn.com/ispeak-bber/ispeak-bber.min.js&quot; charset=&quot;utf-8&quot; &gt;&lt;/script&gt; --&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 解析微信表情（参考：https://github.com/buddys/qq-wechat-emotion-parser） --&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- &lt;script src=&quot;https://cdn.jsdelivr.net/gh/buddys/qq-wechat-emotion-parser@master/dist/qq-wechat-emotion-parser.min.js&quot;&gt;&lt;/script&gt; --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">ispeakBber</span></span><br><span class="line"><span class="language-javascript">    .<span class="title function_">init</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">el</span>: <span class="string">&#x27;#speak&#x27;</span>, <span class="comment">// 容器选择器</span></span></span><br><span class="line"><span class="language-javascript">      <span class="attr">name</span>: <span class="string">&#x27;garvey 🦄&#x27;</span>, <span class="comment">// 显示的昵称</span></span></span><br><span class="line"><span class="language-javascript">      <span class="attr">envId</span>: <span class="string">&#x27;腾讯云开发环境id&#x27;</span>, <span class="comment">// 环境id</span></span></span><br><span class="line"><span class="language-javascript">      <span class="attr">region</span>: <span class="string">&#x27;ap-shanghai&#x27;</span>, <span class="comment">// 腾讯云地址，默认为上海</span></span></span><br><span class="line"><span class="language-javascript">      <span class="attr">limit</span>: <span class="number">10</span>, <span class="comment">// 每次加载的条数，默认为5</span></span></span><br><span class="line"><span class="language-javascript">      <span class="attr">avatar</span>: <span class="string">&#x27;https://cdn.jsdelivr.net/gh/xxx/avatar.jpg&#x27;</span>, <span class="comment">// 头像地址</span></span></span><br><span class="line"><span class="language-javascript">      <span class="attr">fromColor</span>:<span class="string">&#x27;rgb(245, 150, 170)&#x27;</span>, <span class="comment">// 下方标签背景颜色 默认 rgb(245, 150, 170)</span></span></span><br><span class="line"><span class="language-javascript">      <span class="attr">loadingImg</span>: <span class="string">&#x27;https://7.dusays.com/2021/03/04/d2d5e983e2961.gif&#x27;</span>, <span class="comment">// 自定义loading的图片，示例值为默认值</span></span></span><br><span class="line"><span class="language-javascript">      <span class="attr">dbName</span>:<span class="string">&#x27;talks&#x27;</span> <span class="comment">// 数据的名称，默认talks，避免有人的命名不是这个，所以加入此配置字段。</span></span></span><br><span class="line"><span class="language-javascript">    &#125;)</span></span><br><span class="line"><span class="language-javascript">    .<span class="title function_">then</span>(<span class="keyword">function</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 哔哔加载完成后的回调函数，你可以写你自己的功能</span></span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;哔哔 加载完成&#x27;</span>)</span></span><br><span class="line"><span class="language-javascript">    &#125;)</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>其中，云数据库名称必须为 <code>talks</code> 才可以</p><p><strong>效果：</strong></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/bibi.3thb4m5o4080.webp" alt="bibi"></p><p>仓库地址：<a href="https://gitlab.com/DreamyTZK/ispeak-bber">【DreamyTZK / ispeak-bber】</a></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="网站统计"><a href="#网站统计" class="headerlink" title="网站统计"></a>网站统计</h2><ul><li><a href="https://blog.imzjw.cn/charts/">预览地址</a></li></ul><p>此统计功能来自于 <a href="https://blog.eurkon.com/">Eurkon</a></p><ol><li><p>创建统计页面</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new page charts</span><br></pre></td></tr></table></figure></li><li><p>引入 <code>ECharts.js</code>，在 Butterfly 主题下的配置文件添加。（注意不是在 <code>bottom</code>）</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">inject</span>:</span><br><span class="line">  <span class="attr">head</span>:</span><br><span class="line">    - <span class="language-xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://npm.elemecdn.com/echarts@4.7.0/dist/echarts.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br></pre></td></tr></table></figure></li><li><p>在 <code>butterfly\scripts\helpers\</code> 目录下新建 <code>charts.js</code> 文件</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> cheerio = <span class="built_in">require</span>(<span class="string">&#x27;cheerio&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> moment = <span class="built_in">require</span>(<span class="string">&#x27;moment&#x27;</span>)</span><br><span class="line"></span><br><span class="line">hexo.<span class="property">extend</span>.<span class="property">filter</span>.<span class="title function_">register</span>(<span class="string">&#x27;after_render:html&#x27;</span>, <span class="keyword">function</span> (<span class="params">locals</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> $ = cheerio.<span class="title function_">load</span>(locals)</span><br><span class="line">  <span class="keyword">const</span> post = $(<span class="string">&#x27;#posts-chart&#x27;</span>)</span><br><span class="line">  <span class="keyword">const</span> tag = $(<span class="string">&#x27;#tags-chart&#x27;</span>)</span><br><span class="line">  <span class="keyword">const</span> category = $(<span class="string">&#x27;#categories-chart&#x27;</span>)</span><br><span class="line">  <span class="keyword">let</span> htmlEncode = <span class="literal">false</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (post.<span class="property">length</span> &gt; <span class="number">0</span> || tag.<span class="property">length</span> &gt; <span class="number">0</span> || category.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (post.<span class="property">length</span> &gt; <span class="number">0</span> &amp;&amp; $(<span class="string">&#x27;#postsChart&#x27;</span>).<span class="property">length</span> === <span class="number">0</span>) &#123;</span><br><span class="line">      <span class="keyword">if</span> (post.<span class="title function_">attr</span>(<span class="string">&#x27;data-encode&#x27;</span>) === <span class="string">&#x27;true&#x27;</span>) htmlEncode = <span class="literal">true</span></span><br><span class="line">      post.<span class="title function_">after</span>(<span class="title function_">postsChart</span>())</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (tag.<span class="property">length</span> &gt; <span class="number">0</span> &amp;&amp; $(<span class="string">&#x27;#tagsChart&#x27;</span>).<span class="property">length</span> === <span class="number">0</span>) &#123;</span><br><span class="line">      <span class="keyword">if</span> (tag.<span class="title function_">attr</span>(<span class="string">&#x27;data-encode&#x27;</span>) === <span class="string">&#x27;true&#x27;</span>) htmlEncode = <span class="literal">true</span></span><br><span class="line">      tag.<span class="title function_">after</span>(<span class="title function_">tagsChart</span>(tag.<span class="title function_">attr</span>(<span class="string">&#x27;data-length&#x27;</span>)))</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (category.<span class="property">length</span> &gt; <span class="number">0</span> &amp;&amp; $(<span class="string">&#x27;#categoriesChart&#x27;</span>).<span class="property">length</span> === <span class="number">0</span>) &#123;</span><br><span class="line">      <span class="keyword">if</span> (category.<span class="title function_">attr</span>(<span class="string">&#x27;data-encode&#x27;</span>) === <span class="string">&#x27;true&#x27;</span>) htmlEncode = <span class="literal">true</span></span><br><span class="line">      category.<span class="title function_">after</span>(<span class="title function_">categoriesChart</span>())</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (htmlEncode) &#123;</span><br><span class="line">      <span class="keyword">return</span> $.<span class="title function_">root</span>().<span class="title function_">html</span>().<span class="title function_">replace</span>(<span class="regexp">/&amp;amp;#/g</span>, <span class="string">&#x27;&amp;#&#x27;</span>)</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> $.<span class="title function_">root</span>().<span class="title function_">html</span>()</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> locals</span><br><span class="line">  &#125;</span><br><span class="line">&#125;, <span class="number">15</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">postsChart</span> () &#123;</span><br><span class="line">  <span class="keyword">const</span> startDate = <span class="title function_">moment</span>(<span class="string">&#x27;2020-01&#x27;</span>) <span class="comment">// 博客建站月份或自定义时间</span></span><br><span class="line">  <span class="comment">// const startDate = moment().subtract(1,&#x27;year&#x27;).format(&#x27;YYYY-MM&#x27;); // 一年前的今日，统计近一年的文章发布</span></span><br><span class="line">  <span class="keyword">const</span> endDate = <span class="title function_">moment</span>()</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> monthMap = <span class="keyword">new</span> <span class="title class_">Map</span>()</span><br><span class="line">  <span class="keyword">const</span> dayTime = <span class="number">3600</span> * <span class="number">24</span> * <span class="number">1000</span></span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">let</span> time = startDate; time &lt;= endDate; time += dayTime) &#123;</span><br><span class="line">    <span class="keyword">const</span> month = <span class="title function_">moment</span>(time).<span class="title function_">format</span>(<span class="string">&#x27;YYYY-MM&#x27;</span>)</span><br><span class="line">    <span class="keyword">if</span> (!monthMap.<span class="title function_">has</span>(month)) &#123;</span><br><span class="line">      monthMap.<span class="title function_">set</span>(month, <span class="number">0</span>)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  hexo.<span class="property">locals</span>.<span class="title function_">get</span>(<span class="string">&#x27;posts&#x27;</span>).<span class="title function_">forEach</span>(<span class="keyword">function</span> (<span class="params">post</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> month = post.<span class="property">date</span>.<span class="title function_">format</span>(<span class="string">&#x27;YYYY-MM&#x27;</span>)</span><br><span class="line">    <span class="keyword">if</span> (monthMap.<span class="title function_">has</span>(month)) &#123;</span><br><span class="line">      monthMap.<span class="title function_">set</span>(month, monthMap.<span class="title function_">get</span>(month) + <span class="number">1</span>)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;)</span><br><span class="line">  <span class="keyword">const</span> monthArr = <span class="title class_">JSON</span>.<span class="title function_">stringify</span>([...monthMap.<span class="title function_">keys</span>()])</span><br><span class="line">  <span class="keyword">const</span> monthValueArr = <span class="title class_">JSON</span>.<span class="title function_">stringify</span>([...monthMap.<span class="title function_">values</span>()])</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="string">`</span></span><br><span class="line"><span class="string">  &lt;script id=&quot;postsChart&quot;&gt;</span></span><br><span class="line"><span class="string">    var postsChart = echarts.init(document.getElementById(&#x27;posts-chart&#x27;), &#x27;light&#x27;);</span></span><br><span class="line"><span class="string">    var postsOption = &#123;</span></span><br><span class="line"><span class="string">      textStyle: &#123;</span></span><br><span class="line"><span class="string">        color: &#x27;#FFF&#x27;</span></span><br><span class="line"><span class="string">      &#125;,</span></span><br><span class="line"><span class="string">      title: &#123;</span></span><br><span class="line"><span class="string">        text: &#x27;文章发布统计图&#x27;,</span></span><br><span class="line"><span class="string">        x: &#x27;center&#x27;,</span></span><br><span class="line"><span class="string">        textStyle: &#123;</span></span><br><span class="line"><span class="string">          color: &#x27;#FFF&#x27;</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">      &#125;,</span></span><br><span class="line"><span class="string">      tooltip: &#123;</span></span><br><span class="line"><span class="string">        trigger: &#x27;axis&#x27;</span></span><br><span class="line"><span class="string">      &#125;,</span></span><br><span class="line"><span class="string">      xAxis: &#123;</span></span><br><span class="line"><span class="string">        name: &#x27;日期&#x27;,</span></span><br><span class="line"><span class="string">        type: &#x27;category&#x27;,</span></span><br><span class="line"><span class="string">        axisTick: &#123;</span></span><br><span class="line"><span class="string">          show: false</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        axisLine: &#123;</span></span><br><span class="line"><span class="string">          show: true,</span></span><br><span class="line"><span class="string">          lineStyle: &#123;</span></span><br><span class="line"><span class="string">            color: &#x27;#FFF&#x27;</span></span><br><span class="line"><span class="string">          &#125;</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        data: <span class="subst">$&#123;monthArr&#125;</span></span></span><br><span class="line"><span class="string">      &#125;,</span></span><br><span class="line"><span class="string">      yAxis: &#123;</span></span><br><span class="line"><span class="string">        name: &#x27;文章篇数&#x27;,</span></span><br><span class="line"><span class="string">        type: &#x27;value&#x27;,</span></span><br><span class="line"><span class="string">        splitLine: &#123;</span></span><br><span class="line"><span class="string">          show: false</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        axisTick: &#123;</span></span><br><span class="line"><span class="string">          show: false</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        axisLine: &#123;</span></span><br><span class="line"><span class="string">          show: true,</span></span><br><span class="line"><span class="string">          lineStyle: &#123;</span></span><br><span class="line"><span class="string">            color: &#x27;#FFF&#x27;</span></span><br><span class="line"><span class="string">          &#125;</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">      &#125;,</span></span><br><span class="line"><span class="string">      series: [&#123;</span></span><br><span class="line"><span class="string">        name: &#x27;文章篇数&#x27;,</span></span><br><span class="line"><span class="string">        type: &#x27;line&#x27;,</span></span><br><span class="line"><span class="string">        smooth: true,</span></span><br><span class="line"><span class="string">        lineStyle: &#123;</span></span><br><span class="line"><span class="string">            width: 0</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        showSymbol: false,</span></span><br><span class="line"><span class="string">        itemStyle: &#123;</span></span><br><span class="line"><span class="string">          opacity: 1,</span></span><br><span class="line"><span class="string">          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [&#123;</span></span><br><span class="line"><span class="string">            offset: 0,</span></span><br><span class="line"><span class="string">            color: &#x27;rgba(128, 255, 165)&#x27;</span></span><br><span class="line"><span class="string">          &#125;,</span></span><br><span class="line"><span class="string">          &#123;</span></span><br><span class="line"><span class="string">            offset: 1,</span></span><br><span class="line"><span class="string">            color: &#x27;rgba(1, 191, 236)&#x27;</span></span><br><span class="line"><span class="string">          &#125;])</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        areaStyle: &#123;</span></span><br><span class="line"><span class="string">          opacity: 1,</span></span><br><span class="line"><span class="string">          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [&#123;</span></span><br><span class="line"><span class="string">            offset: 0,</span></span><br><span class="line"><span class="string">            color: &#x27;rgba(128, 255, 165)&#x27;</span></span><br><span class="line"><span class="string">          &#125;, &#123;</span></span><br><span class="line"><span class="string">            offset: 1,</span></span><br><span class="line"><span class="string">            color: &#x27;rgba(1, 191, 236)&#x27;</span></span><br><span class="line"><span class="string">          &#125;])</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        data: <span class="subst">$&#123;monthValueArr&#125;</span>,</span></span><br><span class="line"><span class="string">        markLine: &#123;</span></span><br><span class="line"><span class="string">          data: [&#123;</span></span><br><span class="line"><span class="string">            name: &#x27;平均值&#x27;,</span></span><br><span class="line"><span class="string">            type: &#x27;average&#x27;</span></span><br><span class="line"><span class="string">          &#125;]</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">      &#125;]</span></span><br><span class="line"><span class="string">    &#125;;</span></span><br><span class="line"><span class="string">    postsChart.setOption(postsOption);</span></span><br><span class="line"><span class="string">    window.addEventListener(&quot;resize&quot;, () =&gt; &#123; </span></span><br><span class="line"><span class="string">      postsChart.resize();</span></span><br><span class="line"><span class="string">    &#125;);</span></span><br><span class="line"><span class="string">    &lt;/script&gt;`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">tagsChart</span> (len) &#123;</span><br><span class="line">  <span class="keyword">const</span> tagArr = []</span><br><span class="line">  hexo.<span class="property">locals</span>.<span class="title function_">get</span>(<span class="string">&#x27;tags&#x27;</span>).<span class="title function_">map</span>(<span class="keyword">function</span> (<span class="params">tag</span>) &#123;</span><br><span class="line">    tagArr.<span class="title function_">push</span>(&#123; <span class="attr">name</span>: tag.<span class="property">name</span>, <span class="attr">value</span>: tag.<span class="property">length</span> &#125;)</span><br><span class="line">  &#125;)</span><br><span class="line">  tagArr.<span class="title function_">sort</span>(<span class="function">(<span class="params">a, b</span>) =&gt;</span> &#123; <span class="keyword">return</span> b.<span class="property">value</span> - a.<span class="property">value</span> &#125;)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">let</span> dataLength = <span class="title class_">Math</span>.<span class="title function_">min</span>(tagArr.<span class="property">length</span>, len) || tagArr.<span class="property">length</span></span><br><span class="line">  <span class="keyword">const</span> tagNameArr = []</span><br><span class="line">  <span class="keyword">const</span> tagCountArr = []</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; dataLength; i++) &#123;</span><br><span class="line">    tagNameArr.<span class="title function_">push</span>(tagArr[i].<span class="property">name</span>)</span><br><span class="line">    tagCountArr.<span class="title function_">push</span>(tagArr[i].<span class="property">value</span>)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">const</span> tagNameArrJson = <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(tagNameArr)</span><br><span class="line">  <span class="keyword">const</span> tagCountArrJson = <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(tagCountArr)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="string">`</span></span><br><span class="line"><span class="string">  &lt;script id=&quot;tagsChart&quot;&gt;</span></span><br><span class="line"><span class="string">    var tagsChart = echarts.init(document.getElementById(&#x27;tags-chart&#x27;), &#x27;light&#x27;);</span></span><br><span class="line"><span class="string">    var tagsOption = &#123;</span></span><br><span class="line"><span class="string">      textStyle: &#123;</span></span><br><span class="line"><span class="string">        color: &#x27;#FFF&#x27;</span></span><br><span class="line"><span class="string">      &#125;,</span></span><br><span class="line"><span class="string">      title: &#123;</span></span><br><span class="line"><span class="string">        text: &#x27;Top <span class="subst">$&#123;dataLength&#125;</span> 标签统计图&#x27;,</span></span><br><span class="line"><span class="string">        x: &#x27;center&#x27;,</span></span><br><span class="line"><span class="string">        textStyle: &#123;</span></span><br><span class="line"><span class="string">          color: &#x27;#FFF&#x27;</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">      &#125;,</span></span><br><span class="line"><span class="string">      tooltip: &#123;&#125;,</span></span><br><span class="line"><span class="string">      xAxis: [&#123;</span></span><br><span class="line"><span class="string">        name: &#x27;标签&#x27;,</span></span><br><span class="line"><span class="string">        type: &#x27;category&#x27;,</span></span><br><span class="line"><span class="string">        axisTick: &#123;</span></span><br><span class="line"><span class="string">          show: false</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        axisLine: &#123;</span></span><br><span class="line"><span class="string">          show: true,</span></span><br><span class="line"><span class="string">          lineStyle: &#123;</span></span><br><span class="line"><span class="string">            color: &#x27;#FFF&#x27;</span></span><br><span class="line"><span class="string">          &#125;</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        data: <span class="subst">$&#123;tagNameArrJson&#125;</span></span></span><br><span class="line"><span class="string">      &#125;],</span></span><br><span class="line"><span class="string">      yAxis: [&#123;</span></span><br><span class="line"><span class="string">        name: &#x27;文章篇数&#x27;,</span></span><br><span class="line"><span class="string">        type: &#x27;value&#x27;,</span></span><br><span class="line"><span class="string">        splitLine: &#123;</span></span><br><span class="line"><span class="string">          show: false</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        axisTick: &#123;</span></span><br><span class="line"><span class="string">          show: false</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        axisLine: &#123;</span></span><br><span class="line"><span class="string">          show: true,</span></span><br><span class="line"><span class="string">          lineStyle: &#123;</span></span><br><span class="line"><span class="string">            color: &#x27;#FFF&#x27;</span></span><br><span class="line"><span class="string">          &#125;</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">      &#125;],</span></span><br><span class="line"><span class="string">      series: [&#123;</span></span><br><span class="line"><span class="string">        name: &#x27;文章篇数&#x27;,</span></span><br><span class="line"><span class="string">        type: &#x27;bar&#x27;,</span></span><br><span class="line"><span class="string">        data: <span class="subst">$&#123;tagCountArrJson&#125;</span>,</span></span><br><span class="line"><span class="string">        itemStyle: &#123;</span></span><br><span class="line"><span class="string">          opacity: 1,</span></span><br><span class="line"><span class="string">          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [&#123;</span></span><br><span class="line"><span class="string">            offset: 0,</span></span><br><span class="line"><span class="string">            color: &#x27;rgba(128, 255, 165)&#x27;</span></span><br><span class="line"><span class="string">          &#125;,</span></span><br><span class="line"><span class="string">          &#123;</span></span><br><span class="line"><span class="string">            offset: 1,</span></span><br><span class="line"><span class="string">            color: &#x27;rgba(1, 191, 236)&#x27;</span></span><br><span class="line"><span class="string">          &#125;])</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        emphasis: &#123;</span></span><br><span class="line"><span class="string">          itemStyle: &#123;</span></span><br><span class="line"><span class="string">            opacity: 1,</span></span><br><span class="line"><span class="string">            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [&#123;</span></span><br><span class="line"><span class="string">              offset: 0,</span></span><br><span class="line"><span class="string">              color: &#x27;rgba(128, 255, 195)&#x27;</span></span><br><span class="line"><span class="string">            &#125;,</span></span><br><span class="line"><span class="string">            &#123;</span></span><br><span class="line"><span class="string">              offset: 1,</span></span><br><span class="line"><span class="string">              color: &#x27;rgba(1, 211, 255)&#x27;</span></span><br><span class="line"><span class="string">            &#125;])</span></span><br><span class="line"><span class="string">          &#125;</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        markLine: &#123;</span></span><br><span class="line"><span class="string">          data: [&#123;</span></span><br><span class="line"><span class="string">            name: &#x27;平均值&#x27;,</span></span><br><span class="line"><span class="string">            type: &#x27;average&#x27;</span></span><br><span class="line"><span class="string">          &#125;]</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">      &#125;]</span></span><br><span class="line"><span class="string">    &#125;;</span></span><br><span class="line"><span class="string">    tagsChart.setOption(tagsOption);</span></span><br><span class="line"><span class="string">    window.addEventListener(&quot;resize&quot;, () =&gt; &#123; </span></span><br><span class="line"><span class="string">      tagsChart.resize();</span></span><br><span class="line"><span class="string">    &#125;);</span></span><br><span class="line"><span class="string">    &lt;/script&gt;`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">categoriesChart</span> () &#123;</span><br><span class="line">  <span class="keyword">const</span> categoryArr = []</span><br><span class="line">  hexo.<span class="property">locals</span>.<span class="title function_">get</span>(<span class="string">&#x27;categories&#x27;</span>).<span class="title function_">map</span>(<span class="keyword">function</span> (<span class="params">category</span>) &#123;</span><br><span class="line">    categoryArr.<span class="title function_">push</span>(&#123; <span class="attr">name</span>: category.<span class="property">name</span>, <span class="attr">value</span>: category.<span class="property">length</span> &#125;)</span><br><span class="line">  &#125;)</span><br><span class="line">  categoryArr.<span class="title function_">sort</span>(<span class="function">(<span class="params">a, b</span>) =&gt;</span> &#123; <span class="keyword">return</span> b.<span class="property">value</span> - a.<span class="property">value</span> &#125;);</span><br><span class="line">  <span class="keyword">const</span> categoryArrJson = <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(categoryArr)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="string">`</span></span><br><span class="line"><span class="string">  &lt;script id=&quot;categoriesChart&quot;&gt;</span></span><br><span class="line"><span class="string">    var categoriesChart = echarts.init(document.getElementById(&#x27;categories-chart&#x27;), &#x27;light&#x27;);</span></span><br><span class="line"><span class="string">    var categoriesOption = &#123;</span></span><br><span class="line"><span class="string">      textStyle: &#123;</span></span><br><span class="line"><span class="string">        color: &#x27;#FFF&#x27;</span></span><br><span class="line"><span class="string">      &#125;,</span></span><br><span class="line"><span class="string">      title: &#123;</span></span><br><span class="line"><span class="string">        text: &#x27;文章分类统计图&#x27;,</span></span><br><span class="line"><span class="string">        x: &#x27;center&#x27;,</span></span><br><span class="line"><span class="string">        textStyle: &#123;</span></span><br><span class="line"><span class="string">          color: &#x27;#FFF&#x27;</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">      &#125;,</span></span><br><span class="line"><span class="string">      legend: &#123;</span></span><br><span class="line"><span class="string">        top: &#x27;bottom&#x27;,</span></span><br><span class="line"><span class="string">        textStyle: &#123;</span></span><br><span class="line"><span class="string">          color: &#x27;#FFF&#x27;</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">      &#125;,</span></span><br><span class="line"><span class="string">      tooltip: &#123;</span></span><br><span class="line"><span class="string">        trigger: &#x27;item&#x27;,</span></span><br><span class="line"><span class="string">        formatter: &quot;&#123;a&#125; &lt;br/&gt;&#123;b&#125; : &#123;c&#125; (&#123;d&#125;%)&quot;</span></span><br><span class="line"><span class="string">      &#125;,</span></span><br><span class="line"><span class="string">      series: [&#123;</span></span><br><span class="line"><span class="string">        name: &#x27;文章篇数&#x27;,</span></span><br><span class="line"><span class="string">        type: &#x27;pie&#x27;,</span></span><br><span class="line"><span class="string">        radius: [30, 80],</span></span><br><span class="line"><span class="string">        center: [&#x27;50%&#x27;, &#x27;50%&#x27;],</span></span><br><span class="line"><span class="string">        roseType: &#x27;area&#x27;,</span></span><br><span class="line"><span class="string">        label: &#123;</span></span><br><span class="line"><span class="string">          formatter: &quot;&#123;b&#125; : &#123;c&#125; (&#123;d&#125;%)&quot;</span></span><br><span class="line"><span class="string">        &#125;,</span></span><br><span class="line"><span class="string">        data: <span class="subst">$&#123;categoryArrJson&#125;</span>,</span></span><br><span class="line"><span class="string">        itemStyle: &#123;</span></span><br><span class="line"><span class="string">          emphasis: &#123;</span></span><br><span class="line"><span class="string">            shadowBlur: 10,</span></span><br><span class="line"><span class="string">            shadowOffsetX: 0,</span></span><br><span class="line"><span class="string">            shadowColor: &#x27;rgba(255, 255, 255, 0.5)&#x27;</span></span><br><span class="line"><span class="string">          &#125;</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">      &#125;]</span></span><br><span class="line"><span class="string">    &#125;;</span></span><br><span class="line"><span class="string">    categoriesChart.setOption(categoriesOption);</span></span><br><span class="line"><span class="string">    window.addEventListener(&quot;resize&quot;, () =&gt; &#123; </span></span><br><span class="line"><span class="string">      categoriesChart.resize();</span></span><br><span class="line"><span class="string">    &#125;);</span></span><br><span class="line"><span class="string">    &lt;/script&gt;`</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>在 <code>charts\index.md</code> 添加如下代码</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 文章发布时间统计图 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;posts-chart&quot;</span> <span class="attr">style</span>=<span class="string">&quot;background-color: #20232a; border-radius: 8px; height: 300px; padding: 0.5rem;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 文章标签统计图 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;tags-chart&quot;</span> <span class="attr">data-length</span>=<span class="string">&quot;10&quot;</span> <span class="attr">style</span>=<span class="string">&quot;background-color: #20232a; border-radius: 8px; height: 300px; padding: 0.5rem;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- 文章分类统计图 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;categories-chart&quot;</span> <span class="attr">style</span>=<span class="string">&quot;background-color: #20232a; border-radius: 8px; height: 300px; padding: 0.5rem;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol><p>这个只是文章的统计量，还有针对于网站的统计，请到原文中查阅<a href="https://blog.eurkon.com/post/ef1da941.html">【Hexo 博客访问统计图】</a></p><p>最后 <code>hexo cl &amp;&amp; hexo g &amp;&amp; hexo s</code> 查看效果！</p><h2 id="首页及侧边栏展示-BiBi"><a href="#首页及侧边栏展示-BiBi" class="headerlink" title="首页及侧边栏展示 BiBi"></a>首页及侧边栏展示 BiBi</h2><div class="tabs" id="bibi"><ul class="nav-tabs"><button type="button" class="tab " data-href="bibi-1">预览</button><button type="button" class="tab  active" data-href="bibi-2">配置</button></ul><div class="tab-contents"><div class="tab-item-content" id="bibi-1"><p>首页</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/images.1zho1ufp32hs.webp" alt="images"></p><p>侧边栏</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b74f504f/wi.5ly7clfefqk0.webp" alt="images"></p></div><div class="tab-item-content active" id="bibi-2"><p>请确保你已经配置好哔哔再来使用，此功能来自小康博客！</p><p>这个其实是借助了 Butterfly <a href="https://github.com/jerryc127/hexo-theme-butterfly/releases/tag/3.5.0">3.5.0</a> 添加的自定义侧边栏功能，可以添加自己喜欢的 <code>widget</code>，参考 <a href="https://butterfly.js.org/posts/ea33ab97/">自定義側邊欄</a></p><p>在 <code>source/_data</code>（如果沒有 _data 文件夹，请自行创建），创建一个文件 <code>widget.yml</code></p><div class="note info flat"><p>自定义侧边栏在 <a href="mailto:&#x42;&#117;&#x74;&#116;&#101;&#114;&#102;&#x6c;&#x79;&#64;&#x33;&#x2e;&#x38;&#x2e;&#48;">&#x42;&#117;&#x74;&#116;&#101;&#114;&#102;&#x6c;&#x79;&#64;&#x33;&#x2e;&#x38;&#x2e;&#48;</a> 中写法已更改</p></div><p>所以自然而然教程也得更新！</p><p>添加如下代码</p><p>3.8.0 及以上版本</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">top:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">class_name:</span> <span class="string">latestBB</span></span><br><span class="line">    <span class="attr">id_name:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">碎碎念</span></span><br><span class="line">    <span class="attr">icon:</span> <span class="string">fas</span> <span class="string">fa-bolt</span></span><br><span class="line">    <span class="attr">order:</span> <span class="number">-1</span></span><br><span class="line">    <span class="attr">html:</span> <span class="string">|</span></span><br><span class="line"><span class="string">      &lt;div class=&quot;swiper-container swiper-container-aside&quot;&gt;</span></span><br><span class="line"><span class="string">        &lt;div class=&quot;swiper-wrapper swiper-weapper-aside&quot;&gt;&lt;/div&gt;</span></span><br><span class="line"><span class="string">      &lt;/div&gt;</span></span><br><span class="line"><span class="string">      &lt;a class=&quot;bb-btn button--animated&quot; href=&quot;/talking/&quot; title=&quot;查看全部&quot;&gt;&lt;i class=&quot;far fa-hand-point-right fa-fw&quot;&gt;&lt;/i&gt; 查看更多 &lt;/a&gt;</span></span><br><span class="line"><span class="string">      &lt;script&gt;</span></span><br><span class="line"><span class="string">        window.kkBBConfig = &#123;</span></span><br><span class="line"><span class="string">          limit: 9,</span></span><br><span class="line"><span class="string">          blog:&#x27;/talking/&#x27;,</span></span><br><span class="line"><span class="string">          api_url:</span></span><br><span class="line"><span class="string">            &#x27;https://xxx/json/bber.json&#x27; # 存储 bb json 的地址</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">      &lt;/script&gt;</span></span><br><span class="line"><span class="string">      &lt;script src=&quot;https://npm.elemecdn.com/butterfly-bber-swiper/dist/index.min.js&quot;&gt;&lt;/script&gt;</span></span><br></pre></td></tr></table></figure><p>3.5.0 - 3.8.0 版本</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> <span class="attr">class_name:</span> <span class="string">latestBB</span></span><br><span class="line">  <span class="attr">id_name:</span></span><br><span class="line">  <span class="attr">name:</span> <span class="string">自言自语</span></span><br><span class="line">  <span class="attr">icon:</span> <span class="string">fas</span> <span class="string">fa-bolt</span></span><br><span class="line">  <span class="attr">order:</span> <span class="number">-1</span> <span class="comment"># 排序</span></span><br><span class="line">  <span class="attr">html:</span> <span class="string">|</span></span><br><span class="line"><span class="string">    &lt;div class=&quot;swiper-container swiper-container-aside&quot;&gt;</span></span><br><span class="line"><span class="string">      &lt;div class=&quot;swiper-wrapper swiper-weapper-aside&quot;&gt;&lt;/div&gt;</span></span><br><span class="line"><span class="string">    &lt;/div&gt;</span></span><br><span class="line"><span class="string">    &lt;a class=&quot;bb-btn button--animated&quot; href=&quot;/talking/&quot; title=&quot;查看全部&quot;&gt;&lt;i class=&quot;far fa-hand-point-right fa-fw&quot;&gt;&lt;/i&gt; 查看更多 &lt;/a&gt;</span></span><br><span class="line"><span class="string">    &lt;script&gt;</span></span><br><span class="line"><span class="string">      window.kkBBConfig = &#123;</span></span><br><span class="line"><span class="string">        limit: 9,</span></span><br><span class="line"><span class="string">        blog:&#x27;/talking/&#x27;,</span></span><br><span class="line"><span class="string">        api_url:</span></span><br><span class="line"><span class="string">          &#x27;https://xxx/json/bber.json&#x27; # 存储 bb json 的地址</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">    &lt;/script&gt;</span></span><br><span class="line"><span class="string">    &lt;script src=&quot;https://npm.elemecdn.com/butterfly-bber-swiper/dist/index.min.js&quot;&gt;&lt;/script&gt;</span></span><br></pre></td></tr></table></figure><p>其中 <code>latestBB</code> 容器 class 名，不要更改</p><p>HTML 内容！</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;swiper-container swiper-container-aside&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;swiper-wrapper swiper-weapper-aside&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--点击后跳转的链接，指你哔哔的页面 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">&quot;bb-btn button--animated&quot;</span> <span class="attr">href</span>=<span class="string">&quot;/talking/&quot;</span> <span class="attr">title</span>=<span class="string">&quot;查看全部&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&quot;far fa-hand-point-right fa-fw&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span> 查看更多 <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">window</span>.<span class="property">kkBBConfig</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">limit</span>: <span class="number">9</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 点击后跳转的链接，指你哔哔的页面</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">blog</span>:<span class="string">&#x27;/talking/&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 可以是 json 文件地址，也可以是 api 地址</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">api_url</span>:</span></span><br><span class="line"><span class="language-javascript">          <span class="string">&#x27;https://xxx/json/bber.json&#x27;</span></span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://npm.elemecdn.com/butterfly-bber-swiper/dist/index.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>最后 Hexo 三连即可查看效果！</p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="添加-WOW-动画效果"><a href="#添加-WOW-动画效果" class="headerlink" title="添加 WOW 动画效果"></a>添加 WOW 动画效果</h2><p>如需其它配置方案，可参考店长的 <a href="https://akilar.top/posts/abab51cf/#%E6%8F%92%E4%BB%B6%E5%8C%96%E9%85%8D%E7%BD%AE%E6%96%B9%E6%A1%88">插件化配置方案</a> 、<a href="https://akilar.top/posts/abab51cf/#%E5%A4%96%E6%8C%82%E6%A0%87%E7%AD%BE%E5%86%99%E6%B3%95%E9%85%8D%E7%BD%AE%E6%96%B9%E6%A1%88">外挂标签写法配置方案</a></p><p>在 <code>butterfly\source\js\目录下新建 wow_init.js</code>，配置特性动画的默认项。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">wow = <span class="keyword">new</span> <span class="title function_">WOW</span>(&#123;</span><br><span class="line">  <span class="attr">boxClass</span>: <span class="string">&#x27;wow&#x27;</span>,</span><br><span class="line">  <span class="comment">// 当用户滚动时显示隐藏框的类名称</span></span><br><span class="line">  <span class="attr">animateClass</span>: <span class="string">&#x27;animate__animated&#x27;</span>,</span><br><span class="line">  <span class="comment">// 触发 CSS 动画的类名称（动画库默认为&quot;animate.css&quot;库）</span></span><br><span class="line">  <span class="attr">offset</span>: <span class="number">0</span>,</span><br><span class="line">  <span class="comment">// 定义浏览器视口底部与隐藏框顶部之间的距离。</span></span><br><span class="line">  <span class="comment">// 当用户滚动并到达此距离时，将显示隐藏的框。</span></span><br><span class="line">  <span class="attr">mobile</span>: <span class="literal">false</span>,</span><br><span class="line">  <span class="comment">// 在移动设备上打开/关闭wow.js。</span></span><br><span class="line">  <span class="attr">live</span>: <span class="literal">true</span></span><br><span class="line">  <span class="comment">// 在页面上检查新的 wow.js元素。</span></span><br><span class="line">&#125;)</span><br><span class="line">wow.<span class="title function_">init</span>();</span><br></pre></td></tr></table></figure><p>在主题配置文件下找到 <code>inject</code> 配置项，引入 css 和 js</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">inject:</span></span><br><span class="line">  <span class="attr">head:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">&lt;link</span> <span class="string">rel=&quot;stylesheet&quot;</span> <span class="string">href=&quot;https://npm.elemecdn.com/animate.css@4.1.1/animate.min.css&quot;</span> <span class="string">media=&quot;defer&quot;</span> <span class="string">onload=&quot;this.media=&#x27;all&#x27;&quot;&gt;</span></span><br><span class="line">  <span class="attr">bottom:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">&lt;script</span> <span class="string">defer</span> <span class="string">src=&quot;https://cdn.jsdelivr.net/gh/graingert/wow@1.3.0/dist/wow.min.js&quot;&gt;&lt;/script&gt;</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">&lt;script</span> <span class="string">defer</span> <span class="string">data-pjax</span> <span class="string">src=&quot;/js/wow_init.js&quot;&gt;&lt;/script&gt;</span></span><br></pre></td></tr></table></figure><h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><ul><li><p>页面内写法（指 page 页面或者 posts 页面）</p><p>在需要添加动画效果的页面加上 <code>&lt;div class=&#39;example&#39;&gt;&lt;div&gt;</code></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;example wow animate__bounceInUp&quot;</span>&gt;</span></span><br><span class="line">我是内容</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>pug 写法</p><p>例如给首页文章卡片套上动画</p><figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mixin postUI(posts)</span><br><span class="line">  each article , index in page.posts.data</span><br><span class="line"><span class="deletion">-    .recent-post-item</span></span><br><span class="line"><span class="addition">+    .recent-post-item.wow.animate__zoomIn</span></span><br><span class="line">      - let link = article.link || article.path</span><br><span class="line">      - let title = article.title || _p(&#x27;no_title&#x27;)</span><br></pre></td></tr></table></figure></li><li><p>js 批量添加写法（引入顺序需要在 <code>wow_init.js</code> 之前，而且需要 <code>pjax</code> 重载，每页重新添加一遍 class）</p><p>通过在页面按 <kbd>F12</kbd>，使用控制台元素选择器找到对应元素并获取 <code>class</code> 类名</p><p>修改 <code>butterfly\source\js\wow_init.js</code>，在原有内容之前添加内容。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 首页文章卡片动画</span></span><br><span class="line"><span class="keyword">var</span> arr = <span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&quot;recent-post-item&quot;</span>);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; arr.<span class="property">length</span>; i++) &#123;</span><br><span class="line">    arr[i].<span class="property">classList</span>.<span class="title function_">add</span>(<span class="string">&quot;wow&quot;</span>); <span class="comment">// 必要项，添加wow.js标记</span></span><br><span class="line">    arr[i].<span class="property">classList</span>.<span class="title function_">add</span>(<span class="string">&quot;animate__flipInX&quot;</span>); <span class="comment">// 必要项，添加样式动画</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 友链动画</span></span><br><span class="line"><span class="keyword">var</span> arr = <span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&quot;flink-list-item&quot;</span>);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; arr.<span class="property">length</span>; i++) &#123;</span><br><span class="line">    arr[i].<span class="property">classList</span>.<span class="title function_">add</span>(<span class="string">&quot;wow&quot;</span>);</span><br><span class="line">    arr[i].<span class="property">classList</span>.<span class="title function_">add</span>(<span class="string">&quot;animate__shakeY&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 标签动画</span></span><br><span class="line"><span class="keyword">var</span> arr = <span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&quot;tag-cloud-list is-center&quot;</span>);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; arr.<span class="property">length</span>; i++) &#123;</span><br><span class="line">    arr[i].<span class="property">classList</span>.<span class="title function_">add</span>(<span class="string">&quot;wow&quot;</span>);</span><br><span class="line">    arr[i].<span class="property">classList</span>.<span class="title function_">add</span>(<span class="string">&quot;animate__slideInUp&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 初始化函数 动画效果预览: https://animate.style/</span></span><br><span class="line">wow = <span class="keyword">new</span> <span class="title function_">WOW</span>(&#123;</span><br><span class="line">    <span class="comment">// 当用户滚动时显示隐藏框的类名称</span></span><br><span class="line">    <span class="attr">boxClass</span>: <span class="string">&#x27;wow&#x27;</span>,</span><br><span class="line">    <span class="comment">// 触发 CSS 动画的类名称（动画库默认为&quot;animate.css&quot;库）</span></span><br><span class="line">    <span class="attr">animateClass</span>: <span class="string">&#x27;animate__animated&#x27;</span>,</span><br><span class="line">    <span class="comment">// 定义浏览器视口底部与隐藏框顶部之间的距离。</span></span><br><span class="line">    <span class="comment">// 当用户滚动并到达此距离时，将显示隐藏的框。</span></span><br><span class="line">    <span class="attr">offset</span>: <span class="number">0</span>,</span><br><span class="line">    <span class="comment">// 在移动设备上打开/关闭wow.js。</span></span><br><span class="line">    <span class="attr">mobile</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="comment">// 在页面上检查新的 wow.js元素。</span></span><br><span class="line">    <span class="attr">live</span>: <span class="literal">true</span></span><br><span class="line">&#125;)</span><br><span class="line">wow.<span class="title function_">init</span>();</span><br></pre></td></tr></table></figure></li></ul><p>hexo 三连即可看到效果，更多动画样式可以查看 <a href="https://animate.style/">【animate.css 参考文档】</a></p><h2 id="特别鸣谢"><a href="#特别鸣谢" class="headerlink" title="特别鸣谢"></a>特别鸣谢</h2><ul><li><a href="https://immyw.com/">MYW - Butterfly 主题开发者</a></li><li><a href="https://zfe.space/">小冰博客 - 魔改达人</a></li><li><a href="https://akilar.top/">Akilarの糖果屋 - 魔改达人</a></li><li><a href="https://www.antmoe.com/">小康博客 - 美化达人</a></li></ul>]]></content>
    
    
    <summary type="html">折腾 Butterfly 主题也有一年多了，也是时候写篇文章记录一下本站的所有美化，美化过的一点一滴都会记录在此篇文章里，后续也会在此篇文章更新！PS：基本没修改过源码！本博主 Butterfly 版本 3.7.1</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="Butterfly" scheme="https://blog.imzjw.cn/tags/Butterfly/"/>
    
    <category term="美化" scheme="https://blog.imzjw.cn/tags/%E7%BE%8E%E5%8C%96/"/>
    
  </entry>
  
  <entry>
    <title>跨云盘转存的正确方式</title>
    <link href="https://blog.imzjw.cn/posts/e68c1d98/"/>
    <id>https://blog.imzjw.cn/posts/e68c1d98/</id>
    <published>2021-01-31T11:05:04.000Z</published>
    <updated>2021-01-31T11:05:04.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>转存工具目前有挺多，比如 <a href="https://rclone.org/">Rclone</a>，<a href="https://www.airexplorer.net/en/">Air Explorer</a>，<a href="https://softgateon.herokuapp.com/urltodrive/">Copy, URL to Google Drive™</a>，<a href="https://github.com/donwa/gclone">gclone</a>，还有 <a href="https://github.com/iwestlin/gd-utils">gd-utils</a> 等..太多了，就不全列出来了，都各有千秋</p><p>本篇文章讲的是 mover 这款快速转存工具，相比上面那些，这款优点是方便、简单，易上手，能实现跨云盘转存</p><h2 id="开始"><a href="#开始" class="headerlink" title="开始"></a>开始</h2><p>以 Google Drive 转存 A1P 账号为例</p><p>官网地址：<a href="https://mover.io/">https://mover.io</a>  点击 LOGIN</p><p>之前是 email 注册的，而现在改了，直接用微软账号登录授权即可</p><p>授权成功后你就会来到这个界面</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20240503090845.3k7tfseyqv.webp" alt="images"></p><p>左侧表示源目标，右侧表示目的地，通俗一点讲也就是左侧的资源要转存到右侧去</p><p>在左侧那里点击 Authorize New Connector 进行授权</p><p>可以看到基本主流的云盘都支持</p><p>这里我选择 Google Drive</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/20240503/blog20240503091635.6pnbeqg4yd.webp" alt="images"></p><p>接着取个名字好分辨，点击 Authorize</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/20240503/blog20240503091621.2h844wptm7.webp" alt="blog20240503091621"></p><p>就会跳到 google 这里进行登录授权</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/20240503/blog20240503091609.8dwobx6ckv.webp" alt="blog20240503091609" style="zoom:50%;" /><p>授权成功之后左侧就会列出你 google drive 的所有内容了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/cpddo/p_img@09cc72757fcdd264bef452e727e430efca6d6d34/2021/01/31/c460653ba564a127f053e9e83680dec9.webp" alt="img"></p><p>接着在右侧进行授权，步骤和刚刚是一模一样</p><p>Mover 这款工具缺点就是目标云盘只能选择 OneDrive，没办法（微软的免费工具当然是支持微软的产品啦）</p><p>选择 OneDrive for Business 进行登录授权</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/20240503/blog20240503091553.7i06wgwo4u.webp" alt="blog20240503091553"></p><p>准备工作都已完成，开始转存</p><p>以约定的梦幻岛为例子，然后点击  <code>start copy</code>  开始转存（20 : 07 开始转存）</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/20240503/blog20240503091535.64dnsflm3x.webp" alt="blog20240503091535"></p><p>20 : 09 就发邮件通知你转存成功了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/20240503/blog20240503091414.361doxdcmg.webp" alt="blog20240503091414"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/20240503/blog20240503091441.4uaqm43msq.webp" alt="blog20240503091441"></p><p><code>3.4G</code> 的东西仅仅两分钟完成（准确来讲是一分半）速度相当 perfect</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/20240503/blog20240503091455.8kzw7csi0b.webp" alt="blog20240503091455"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://jsd.cdn.zzko.cn/gh/msyouq/picx-images-hosting@master/20240503/blog20240503091508.5j4064r5t9.webp" alt="blog20240503091508"></p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><h3 id="缺点"><a href="#缺点" class="headerlink" title="缺点"></a>缺点</h3><p>A1，E5，A1P 等等，限制单文件大小 15 G</p><p>个人盘限制单文件大小 10 G</p><p>只能转存到 OneDrive，不能转到其他云盘</p><h3 id="优点"><a href="#优点" class="headerlink" title="优点"></a>优点</h3><p>免费（白嫖党最爱）</p><p>不限制网盘数，不限制总流量</p><p>支持不同域的 OneDrive</p><p>可以自动跳过同目录重复文件</p>]]></content>
    
    
    <summary type="html">转存工具目前有挺多，比如 Rclone，Air Explorer，Copy, URL to Google Drive™，gclone，还有 gd-utils 等..太多了，就不全列出来了，都各有千秋 本篇文章讲的是 mover 这款快速转存工具，相比上面那些，这款优点是方便、简单，易上手...</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="云盘转存" scheme="https://blog.imzjw.cn/tags/%E4%BA%91%E7%9B%98%E8%BD%AC%E5%AD%98/"/>
    
  </entry>
  
  <entry>
    <title>资源搜索下载网站</title>
    <link href="https://blog.imzjw.cn/posts/1dd3d913/"/>
    <id>https://blog.imzjw.cn/posts/1dd3d913/</id>
    <published>2021-01-28T10:39:28.000Z</published>
    <updated>2021-01-28T10:39:28.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="unblockninja"><a href="#unblockninja" class="headerlink" title="unblockninja"></a>unblockninja</h2><p><a href="https://unblockninja.com/">https://unblockninja.com/</a></p><p>这个类似于集合（二十个都是非常出名的，其中就包括了海盗湾）</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1dd3d913/c3546c7aa652e9436994ed873c81e448.webp" alt="img"><h2 id="动漫花园"><a href="#动漫花园" class="headerlink" title="动漫花园"></a>动漫花园</h2><p><a href="http://share.dmhy.org/">http://share.dmhy.org/</a></p><p>是一个动漫爱好者交流的平台，提供最及时，最全面的动画、漫画、动漫音乐、动漫下载</p><p>只提供磁力链接下载</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1dd3d913/0afb359464c9a9c05b096ea5e0ae50ab.webp" alt="img"><h2 id="ACG动漫"><a href="#ACG动漫" class="headerlink" title="ACG动漫"></a>ACG动漫</h2><p><a href="https://acg.rip/">https://acg.rip/</a></p><p>只提供 BT 种子下载</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1dd3d913/bae9260eb048f8f2e50e5d46e409d50f.webp" alt="img"><h2 id="音范丝"><a href="#音范丝" class="headerlink" title="音范丝"></a>音范丝</h2><p><a href="http://www.yinfans.me/">http://www.yinfans.me/</a></p><p>一个电影爱好者的资讯分享站，精选 4K 蓝光原盘下载</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1dd3d913/319cce2d390ad67d0226912a2e041404.webp" alt="img"><h2 id="影视森林"><a href="#影视森林" class="headerlink" title="影视森林"></a>影视森林</h2><p><a href="http://www.549.tv/">http://www.549.tv/</a></p><p>一个导航站，汇集了各种优质影视站，搜索，资源</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1dd3d913/c8323768632656717760d538bb4a2cc8.webp" alt="img"><h2 id="字幕站"><a href="#字幕站" class="headerlink" title="字幕站"></a>字幕站</h2><p>这里讲几个字幕下载站</p><h3 id="伪射手"><a href="#伪射手" class="headerlink" title="伪射手"></a>伪射手</h3><p><a href="http://secure.assrt.net/">http://secure.assrt.net/</a></p><p>该站从界面到底部链接，完全仿照原射手。但中文搜索是软肋，通过中文搜索，索引到原射手字幕数据，可能还没有完全解决。英文搜索完美。支持字幕上传功能。</p><h3 id="点点字幕"><a href="#点点字幕" class="headerlink" title="点点字幕"></a>点点字幕</h3><p><a href="http://www.ddzimu.com/">http://www.ddzimu.com</a></p><p>点点字幕提供大量电影及美剧字幕资源，首页为影片搜索，方便搜索字幕</p><h3 id="OpenSubtitles"><a href="#OpenSubtitles" class="headerlink" title="OpenSubtitles"></a>OpenSubtitles</h3><p><a href="http://www.opensubtitles.org/">http://www.opensubtitles.org</a></p><p>国际知名字幕网站，提供各国语言的字幕下载。射手关站后，OpenSubtitles 站长表示，会导入射手字幕数据。但中文搜索功能、界面的水土不服，还是让人难以寄予厚望。</p><h3 id="A7美剧字幕站"><a href="#A7美剧字幕站" class="headerlink" title="A7美剧字幕站"></a>A7美剧字幕站</h3><p><a href="http://www.addic7ed.com/">http://www.addic7ed.com/</a></p><p>人人影视关站页面推荐过的站，各国字幕都有。无中文界面。</p><h3 id="Subscene"><a href="#Subscene" class="headerlink" title="Subscene"></a>Subscene</h3><p><a href="http://subscene.com/">http://subscene.com/</a> </p><p>国外字幕站，国语字幕大部是港台影迷上传，所以繁体字幕为主，可以转换为简体字幕后使用。</p>]]></content>
    
    
    <summary type="html">动漫花园是一个动漫爱好者交流的平台，提供最及时，最全面的动画、漫画、动漫音乐、动漫下载，只提供磁力链接下载，音范丝是一个电影爱好者的资讯分享站，精选 4K蓝光原盘下载，影视森林一个导航站，汇集了各种优质影视站，搜索，资源</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="资源搜索" scheme="https://blog.imzjw.cn/tags/%E8%B5%84%E6%BA%90%E6%90%9C%E7%B4%A2/"/>
    
  </entry>
  
  <entry>
    <title>介绍一款自动生成数据库文档工具</title>
    <link href="https://blog.imzjw.cn/posts/screw/"/>
    <id>https://blog.imzjw.cn/posts/screw/</id>
    <published>2021-01-27T02:47:40.000Z</published>
    <updated>2021-01-27T02:47:40.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>我们在开发的时候，花费太多时间来编写数据库表结构文档，关于数据库表结构文档状态就是要么没有，要么有、但那都是手写，后期运维开发，需要手动进行维护到文档中，非常繁琐，如果忘记一次维护，就会给以后工作造成很多困扰、无形中制造了很多坑留给自己和后人，于是我们可以用 screw 插件工具来维护。感谢大佬的无私奉献</p><h2 id="特点"><a href="#特点" class="headerlink" title="特点"></a>特点</h2><ul><li>screw 是一个简洁、轻量、设计良好。不需要 powerdesigner 这种重量的建模工具</li><li>多数据库支持，目前支持市面常见的数据库类型 MySQL、Oracle、SqlServer 等..</li><li>多种格式文档。支持 MD、HTML、WORD 格式</li><li>灵活扩展。支持用户自定义模板和展示样式</li></ul><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><p>这里以 MySQL 5.7 为例子</p><p>screw 它有两种方式生成</p><h3 id="第一种"><a href="#第一种" class="headerlink" title="第一种"></a>第一种</h3><p>也是最普通的一种</p><ol><li><p>首先引入依赖</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.1.47<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>cn.smallbun.screw<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>screw-core<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0.3<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.zaxxer<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>HikariCP<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.4.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>以代码的方式配置文档生成</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">generateDocs</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="comment">// 数据源</span></span><br><span class="line">    <span class="type">HikariConfig</span> <span class="variable">hikariConfig</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HikariConfig</span>();</span><br><span class="line">    hikariConfig.setDriverClassName(<span class="string">&quot;com.mysql.jdbc.Driver&quot;</span>);</span><br><span class="line">    hikariConfig.setJdbcUrl(<span class="string">&quot;jdbc:mysql:///spring&quot;</span>);</span><br><span class="line">    hikariConfig.setUsername(<span class="string">&quot;root&quot;</span>);</span><br><span class="line">    hikariConfig.setPassword(<span class="string">&quot;root&quot;</span>);</span><br><span class="line">    <span class="comment">// 设置可以获取tables remarks信息</span></span><br><span class="line">    hikariConfig.addDataSourceProperty(<span class="string">&quot;useInformationSchema&quot;</span>, <span class="string">&quot;true&quot;</span>);</span><br><span class="line">    hikariConfig.setMinimumIdle(<span class="number">2</span>);</span><br><span class="line">    hikariConfig.setMaximumPoolSize(<span class="number">5</span>);</span><br><span class="line">    <span class="type">DataSource</span> <span class="variable">dataSource</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HikariDataSource</span>(hikariConfig);</span><br><span class="line">    <span class="comment">// 生成配置</span></span><br><span class="line">    <span class="type">EngineConfig</span> <span class="variable">engineConfig</span> <span class="operator">=</span> EngineConfig.builder()</span><br><span class="line">        <span class="comment">// 生成文件路径</span></span><br><span class="line">        .fileOutputDir(<span class="string">&quot;C:\\Users\\garvey\\Desktop\\Demo&quot;</span>)</span><br><span class="line">        <span class="comment">// 生成完成之后是否打开目录</span></span><br><span class="line">        .openOutputDir(<span class="literal">true</span>)</span><br><span class="line">        <span class="comment">// 生成的文件类型（HTML、WORD、MD）</span></span><br><span class="line">        .fileType(EngineFileType.HTML)</span><br><span class="line">        <span class="comment">// 生成模板实现</span></span><br><span class="line">        .produceType(EngineTemplateType.freemarker).build();</span><br><span class="line">    <span class="comment">// 忽略表（根据需求配置）</span></span><br><span class="line">    ArrayList&lt;String&gt; ignoreTableName = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">    ignoreTableName.add(<span class="string">&quot;test_user&quot;</span>);</span><br><span class="line">    ignoreTableName.add(<span class="string">&quot;test_group&quot;</span>);</span><br><span class="line">    <span class="comment">// 忽略表前缀（根据需求配置）</span></span><br><span class="line">    ArrayList&lt;String&gt; ignorePrefix = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">    ignorePrefix.add(<span class="string">&quot;test_&quot;</span>);</span><br><span class="line">    <span class="comment">// 忽略表后缀（根据需求配置）</span></span><br><span class="line">    ArrayList&lt;String&gt; ignoreSuffix = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">    ignoreSuffix.add(<span class="string">&quot;_test&quot;</span>);</span><br><span class="line">    <span class="type">ProcessConfig</span> <span class="variable">processConfig</span> <span class="operator">=</span> ProcessConfig.builder()</span><br><span class="line">        <span class="comment">// 忽略表名（根据需求配置）</span></span><br><span class="line">        .ignoreTableName(ignoreTableName)</span><br><span class="line">        <span class="comment">// 忽略表前缀（根据需求配置）</span></span><br><span class="line">        .ignoreTablePrefix(ignorePrefix)</span><br><span class="line">        <span class="comment">// 忽略表后缀（根据需求配置）</span></span><br><span class="line">        .ignoreTableSuffix(ignoreSuffix).build();</span><br><span class="line">    <span class="comment">// 配置</span></span><br><span class="line">    <span class="type">Configuration</span> <span class="variable">config</span> <span class="operator">=</span> Configuration.builder()</span><br><span class="line">        <span class="comment">// 版本</span></span><br><span class="line">        .version(<span class="string">&quot;1.0.0&quot;</span>)</span><br><span class="line">        <span class="comment">// 描述</span></span><br><span class="line">        .description(<span class="string">&quot;数据库设计文档生成&quot;</span>)</span><br><span class="line">        <span class="comment">// 数据源</span></span><br><span class="line">        .dataSource(dataSource)</span><br><span class="line">        <span class="comment">// 生成配置</span></span><br><span class="line">        .engineConfig(engineConfig)</span><br><span class="line">        <span class="comment">// 生成配置</span></span><br><span class="line">        .produceConfig(processConfig).build();</span><br><span class="line">    <span class="comment">// 执行生成</span></span><br><span class="line">    <span class="keyword">new</span> <span class="title class_">DocumentationExecute</span>(config).execute();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>运行（ <code>HTML</code> ）</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/screw/1b6ae70fb0a35e09e1ad56c292662395.webp" alt="HTML"></p><p><code>WORD</code></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/screw/95575df0bb20c03ead506945b1763819.webp" alt="WORD"><p><code>Markdown</code></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/screw/f9fbfcc22bce004ecc1434b106999bc0.webp" alt="Markdown"></li></ol><h3 id="第二种"><a href="#第二种" class="headerlink" title="第二种"></a>第二种</h3><p>则是以 maven 插件的方式</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>cn.smallbun.screw<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>screw-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!-- HikariCP --&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.zaxxer<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>HikariCP<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.4.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!--mysql driver--&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.1.47<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!--username--&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">username</span>&gt;</span>root<span class="tag">&lt;/<span class="name">username</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!--password--&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">password</span>&gt;</span>root<span class="tag">&lt;/<span class="name">password</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!--driver--&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">driverClassName</span>&gt;</span>com.mysql.jdbc.Driver<span class="tag">&lt;/<span class="name">driverClassName</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!--jdbc url--&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">jdbcUrl</span>&gt;</span>jdbc:mysql:///spring<span class="tag">&lt;/<span class="name">jdbcUrl</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!--生成文件类型--&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">fileType</span>&gt;</span>HTML<span class="tag">&lt;/<span class="name">fileType</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!--文件输出目录--&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">fileOutputDir</span>&gt;</span>C:\Users\garvey\Desktop\Demo<span class="tag">&lt;/<span class="name">fileOutputDir</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!--打开文件输出目录--&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">openOutputDir</span>&gt;</span>false<span class="tag">&lt;/<span class="name">openOutputDir</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!--生成模板--&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">produceType</span>&gt;</span>freemarker<span class="tag">&lt;/<span class="name">produceType</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!--描述--&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">description</span>&gt;</span>数据库文档生成<span class="tag">&lt;/<span class="name">description</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!--版本--&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;project.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!--标题--&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">title</span>&gt;</span>数据库文档<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">executions</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">phase</span>&gt;</span>compile<span class="tag">&lt;/<span class="name">phase</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">goals</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">goal</span>&gt;</span>run<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">executions</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br></pre></td></tr></table></figure><p>配置完成后点击 compile</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/screw/2fb6a993b4ab5f670711e1a4ff4651ad.webp" alt="compile"></p><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><ol><li><p>生成后文档如果乱码在 URL 加入 <code>?characterEncoding=UTF-8</code></p></li><li><p>如果报错信息为 <code>Caused by: java.lang.NoSuchFieldError: VERSION_2_3_30</code>，请检查项目 <code>freemarker</code> 依赖，这是由于版本过低造成的，升级版本为 <code>2.3.30</code> 即可</p></li><li><p><code>java.lang.AbstractMethodError:oracle.jdbc.driver.T4CConnection.getSchema()java.lang.String</code></p><p><code>Oracle</code> 驱动版本过低造成的，删除或屏蔽目前驱动版本，驱动添加升级为以下版本</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.oracle.ojdbc<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>ojdbc8<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>19.3.0.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>cn.easyproject<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>orai18n<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>12.1.0.2.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol><p>项目地址：</p><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/pingfangushi/screw"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=pingfangushi&repo=screw&theme=buefy&show_owner=true"/></a>]]></content>
    
    
    <summary type="html">我们在开发的时候，花费太多时间来编写数据库表结构文档，关于数据库表结构文档状态就是要么没有，要么有、但那都是手写，后期运维开发，需要手动进行维护到文档中，非常繁琐，如果忘记一次维护，就会给以后工作造成很多困扰、无形中制造了很多坑留给自己和后人</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="screw" scheme="https://blog.imzjw.cn/tags/screw/"/>
    
  </entry>
  
  <entry>
    <title>使用 Spring 的 IOC 实现账户的 CRUD (注解配置)</title>
    <link href="https://blog.imzjw.cn/posts/c98129ee/"/>
    <id>https://blog.imzjw.cn/posts/c98129ee/</id>
    <published>2021-01-21T13:54:59.000Z</published>
    <updated>2021-01-21T13:54:59.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>注解配置和 <code>xml</code> 配置要实现的功能都是一样的，都是要降低程序间的耦合。只是配置的形式不一样。关于实际的开发中到底使用<code>xml</code>还是注解，每家公司有着不同的使用习惯。所以这两种配置方式我们都需要掌握。</p><div class="note primary flat"><p>本文的注解配置，采用 <a href="https://blog.imzjw.cn/posts/b21d499c/">上篇文章</a> 的案例，把 spring  的 xml 配置内容改为使用注解逐步实现。</p></div><ol><li><p>使用 <code>@Repository</code> 注解管理持久层（省略持久层接口，所改变的是它的实现类）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Repository</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountDaoImpl</span> <span class="keyword">implements</span> <span class="title class_">IAccountDao</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使用 <span class="doctag">@Autowired</span> 注解自动按照类型注入，所以此处无需 setter 方法了</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> QueryRunner queryRunner;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ....</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// ... 此处省略 CRUD 方法，因为和上篇文章是一样的</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>使用 <code>@Service</code> 注解管理 业务层（省略业务层接口，所改变的是它的实现类）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">IAccountService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使用 <span class="doctag">@Autowired</span> 注解自动按照类型注入，所以此处无需 setter 方法了</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> IAccountDao accountDao;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ....</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// ... 此处省略 CRUD 方法，因为和上篇文章是一样的</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>修改 <code>XML</code> 配置文件</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">&quot;http://www.springframework.org/schema/context&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/beans/spring-beans.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/context</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/context/spring-context.xsd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--扫描容器所在的包--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;cn.imzjw&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--配置 queryRunner--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;queryRunner&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.apache.commons.dbutils.QueryRunner&quot;</span> <span class="attr">scope</span>=<span class="string">&quot;prototype&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--注入数据源--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">name</span>=<span class="string">&quot;ds&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;dataSource&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--配置数据源--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.mchange.v2.c3p0.ComboPooledDataSource&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--连接数据库的必备信息--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driverClass&quot;</span> <span class="attr">value</span>=<span class="string">&quot;com.mysql.jdbc.Driver&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;jdbcUrl&quot;</span> <span class="attr">value</span>=<span class="string">&quot;jdbc:mysql://localhost:3306/spring&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;user&quot;</span> <span class="attr">value</span>=<span class="string">&quot;garvey&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;garvey&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>测试类不做改变，测试结果一模一样</p></li></ol><h2 id="常用注解"><a href="#常用注解" class="headerlink" title="常用注解"></a>常用注解</h2><h3 id="用于创建对象的"><a href="#用于创建对象的" class="headerlink" title="用于创建对象的"></a>用于创建对象的</h3><p>相当于XML中的 <code>&lt;bean id=&quot;&quot; class=&quot;&quot;&gt;</code></p><div class="tabs" id="anno"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="anno-1">Component</button><button type="button" class="tab " data-href="anno-2">Controller、Service、Repository</button></ul><div class="tab-contents"><div class="tab-item-content active" id="anno-1"><p>作用：把资源交给 spring 来管理。相当于在 xml 中配置一个 bean</p><p>属性：value：指定 bean 的 id。如果不指定 value 属性，默认 bean 的 id 是当前类的类名。首字母小写。</p></div><div class="tab-item-content" id="anno-2"><p>他们三个注解都是针对一个的衍生注解，他们的作用及属性都是一模一样的。 他们只不过是提供了更加明确的语义化。</p><ul><li>@Controller：一般用于表现层的注解。 </li><li>@Service：一般用于业务层的注解。 </li><li>@Repository：一般用于持久层的注解。</li></ul><p>注：如果注解中有且只有一个属性要赋值时，且名称是 value，value 在赋值是可以不写</p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="用于注入数据的"><a href="#用于注入数据的" class="headerlink" title="用于注入数据的"></a>用于注入数据的</h3><p>相当于XML中的 <code>&lt;property name=&quot;&quot; ref=&quot;&quot;&gt;</code> 和 <code>&lt;property name=&quot;&quot; value=&quot;&quot;&gt;</code></p><div class="tabs" id="anno2"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="anno2-1">Autowired</button><button type="button" class="tab " data-href="anno2-2">Qualifier</button><button type="button" class="tab " data-href="anno2-3">Resource</button><button type="button" class="tab " data-href="anno2-4">Value</button></ul><div class="tab-contents"><div class="tab-item-content active" id="anno2-1"><p>作用：自动按照类型注入。当使用注解注入属性时，set 方法可以省略。它只能注入其他 Bean 类型。当有多个 类型匹配时，使用要注入的对象变量名称作为 Bean 的 id，在 <code>spring</code> 容器查找，找到了也可以注入成功。找不到就报错。</p></div><div class="tab-item-content" id="anno2-2"><ul><li>作用：在自动按照类型注入的基础之上，再按照 Bean 的 id 注入。它在给字段注入时不能独立使用，必须和 <code>@Autowired</code>一起使用；但是给方法参数注入时，可以独立使用。 </li><li>属性：value：指定 bean 的 id。</li></ul></div><div class="tab-item-content" id="anno2-3"><ul><li>作用：直接按照 Bean 的 id 注入。它也只能注入其他 bean 类型。 </li><li>属性：name：指定 bean 的 id。</li></ul></div><div class="tab-item-content" id="anno2-4"><ul><li>作用：注入基本数据类型和 String 类型数据</li><li>属性：value：用于指定值</li></ul></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="用于改变作用范围的"><a href="#用于改变作用范围的" class="headerlink" title="用于改变作用范围的"></a>用于改变作用范围的</h3><p>相当于 XML 中的 <code>&lt;bean id=&quot;&quot; class=&quot;&quot; scope=&quot;&quot;&gt;</code></p><div class="tabs" id="anno3"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="anno3-1">Scope</button></ul><div class="tab-contents"><div class="tab-item-content active" id="anno3-1"><ul><li>作用：指定 bean 的作用范围。 </li><li>属性：value：指定范围的值。 <ul><li>取值：singleton、prototype、request、session、globalsession</li></ul></li></ul></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="和生命周期相关的"><a href="#和生命周期相关的" class="headerlink" title="和生命周期相关的"></a>和生命周期相关的</h3><p>相当于 XML 中的 <code>&lt;bean id=&quot;&quot; class=&quot;&quot; init-method=&quot;&quot; destroy-method=&quot;&quot; /&gt;</code></p><div class="tabs" id="anno4"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="anno4-1">PostConstruct</button><button type="button" class="tab " data-href="anno4-2">PreDestroy</button></ul><div class="tab-contents"><div class="tab-item-content active" id="anno4-1"><p>用于指定初始化方法。</p></div><div class="tab-item-content" id="anno4-2"><p>用于指定销毁方法。</p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="思考"><a href="#思考" class="headerlink" title="思考"></a>思考</h2><p>写到此处，基于注解的 IOC 配置已经完成，但是大家都发现了一个问题，我们依然离不开 Spring 的 XML 配置文件，那么能不能不写这个 bean.xml，所有配置都用注解来实现呢？</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>我们选择哪种配置的原则是简化开发和配置方便，而非追求某种技术。</p>]]></content>
    
    
    <summary type="html">注解配置和 xml 配置要实现的功能都是一样的，都是要降低程序间的耦合。只是配置的形式不一样。关于实际的开发中到底使用 xml 还是注解，每家公司有着不同的使用习惯。所以这两种配置方式我们都需要掌握。</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring" scheme="https://blog.imzjw.cn/tags/Spring/"/>
    
  </entry>
  
  <entry>
    <title>使用 Spring 的 IOC 实现账户的 CRUD (XML配置)</title>
    <link href="https://blog.imzjw.cn/posts/b21d499c/"/>
    <id>https://blog.imzjw.cn/posts/b21d499c/</id>
    <published>2021-01-21T13:08:53.000Z</published>
    <updated>2021-01-21T13:08:53.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h2><p>实现账户的 CRUD 操作</p><h2 id="开始编写"><a href="#开始编写" class="headerlink" title="开始编写"></a>开始编写</h2><ol><li><p>导入maven依赖（pom.xml）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.1.47<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-context<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.2.12.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>commons-dbutils<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>commons-dbutils<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.6<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.mchange<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>c3p0<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>0.9.5.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>junit<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>junit<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.13.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.18.16<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>创建数据库</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> IF <span class="keyword">EXISTS</span> `account`;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> `account` (</span><br><span class="line">  `id` <span class="type">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="keyword">NULL</span> AUTO_INCREMENT,</span><br><span class="line">  `name` <span class="type">varchar</span>(<span class="number">40</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line">  `money` <span class="type">float</span> <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line">  <span class="keyword">PRIMARY</span> KEY (`id`)</span><br><span class="line">) ENGINE<span class="operator">=</span>InnoDB AUTO_INCREMENT<span class="operator">=</span><span class="number">4</span> <span class="keyword">DEFAULT</span> CHARSET<span class="operator">=</span>utf8;</span><br><span class="line"></span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `account` <span class="keyword">VALUES</span> (<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;aaa&#x27;</span>, <span class="string">&#x27;1000&#x27;</span>);</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `account` <span class="keyword">VALUES</span> (<span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;bbb&#x27;</span>, <span class="string">&#x27;1000&#x27;</span>);</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `account` <span class="keyword">VALUES</span> (<span class="string">&#x27;3&#x27;</span>, <span class="string">&#x27;ccc&#x27;</span>, <span class="string">&#x27;1000&#x27;</span>);</span><br></pre></td></tr></table></figure></li><li><p>编写实体类（<code>cn.imzjw.entity.Account.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Account</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">float</span> money;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>编写持久层代码（<code>cn.imzjw.dao.IAccountDao.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">IAccountDao</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询所有</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    List&lt;Account&gt; <span class="title function_">findAllAccount</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询一个</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Account <span class="title function_">findAccountById</span><span class="params">(Integer id)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 保存账户</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">saveAccount</span><span class="params">(Account account)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 删除账户</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">delAccount</span><span class="params">(Integer id)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 更新账户</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">updateAccount</span><span class="params">(Account account)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>持久层接口实现类（<code>cn.imzjw.dao.impl.AccountDaoImpl</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountDaoImpl</span> <span class="keyword">implements</span> <span class="title class_">IAccountDao</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> QueryRunner queryRunner;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setQueryRunner</span><span class="params">(QueryRunner queryRunner)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.queryRunner = queryRunner;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> List&lt;Account&gt; <span class="title function_">findAllAccount</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> queryRunner.query(<span class="string">&quot;SELECT * FROM account&quot;</span>, </span><br><span class="line">                                     <span class="keyword">new</span> <span class="title class_">BeanListHandler</span>&lt;Account&gt;(Account.class));</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Account <span class="title function_">findAccountById</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> queryRunner.query(<span class="string">&quot;SELECT * FROM account WHERE id = ?&quot;</span>, </span><br><span class="line">                                     <span class="keyword">new</span> <span class="title class_">BeanHandler</span>&lt;&gt;(Account.class), id);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">saveAccount</span><span class="params">(Account account)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            queryRunner.update(<span class="string">&quot;INSERT INTO account(name, money) VALUES(?, ?)&quot;</span>, </span><br><span class="line">                               account.getName(), account.getMoney());</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">delAccount</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            queryRunner.update(<span class="string">&quot;DELETE FROM account WHERE id = ?&quot;</span>, id);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">updateAccount</span><span class="params">(Account account)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            queryRunner.update(<span class="string">&quot;UPDATE account SET name = ?, money = ? WHERE id = ?&quot;</span>, </span><br><span class="line">                               account.getName(), account.getMoney(), account.getId());</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>编写业务层代码（<code>cn.imzjw.service.IAccountService.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">IAccountService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询所有</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    List&lt;Account&gt; <span class="title function_">findAllAccount</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询一个</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Account <span class="title function_">findAccountById</span><span class="params">(Integer id)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 保存账户</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">saveAccount</span><span class="params">(Account account)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 删除账户</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">delAccount</span><span class="params">(Integer id)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 更新账户</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">updateAccount</span><span class="params">(Account account)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编写业务层接口实现类（<code>cn.imzjw.service.impl.AccountServiceImpl.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">IAccountService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> IAccountDao accountDao;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setAccountDao</span><span class="params">(IAccountDao accountDao)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.accountDao = accountDao;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> List&lt;Account&gt; <span class="title function_">findAllAccount</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> accountDao.findAllAccount();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Account <span class="title function_">findAccountById</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> accountDao.findAccountById(id);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">saveAccount</span><span class="params">(Account account)</span> &#123;</span><br><span class="line">        accountDao.saveAccount(account);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">delAccount</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line">        accountDao.delAccount(id);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">updateAccount</span><span class="params">(Account account)</span> &#123;</span><br><span class="line">        accountDao.updateAccount(account);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>在<code>resources</code>下<code>new</code>一个<code>xml</code>配置文件，命名随意，但不可中文，配置文件代码如下：</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/beans/spring-beans.xsd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--配置 service --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;accountService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;cn.imzjw.service.impl.AccountServiceImpl&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--注入 accountDao --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;accountDao&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;accountDaoImpl&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--配置持久层--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;accountDaoImpl&quot;</span> <span class="attr">class</span>=<span class="string">&quot;cn.imzjw.dao.impl.AccountDaoImpl&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--注入 queryRunner --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;queryRunner&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;queryRunner&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--配置 queryRunner--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;queryRunner&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.apache.commons.dbutils.QueryRunner&quot;</span> <span class="attr">scope</span>=<span class="string">&quot;singleton&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--注入数据源--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">name</span>=<span class="string">&quot;ds&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;dataSource&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--配置数据源--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.mchange.v2.c3p0.ComboPooledDataSource&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--连接数据库的必备信息--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driverClass&quot;</span> <span class="attr">value</span>=<span class="string">&quot;com.mysql.jdbc.Driver&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;jdbcUrl&quot;</span> <span class="attr">value</span>=<span class="string">&quot;jdbc:mysql://localhost:3306/spring&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;user&quot;</span> <span class="attr">value</span>=<span class="string">&quot;garvey&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;garvey&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol><div class="note success flat"><p>经过如上一番配置，现在开始进行测试 </p></div><p>在<code>test</code>包下新建测试类，如图，这是我的项目结构</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/b21d499c/9c5bbf679fdee0c39d5eba0eaf9f8208.webp" height="450" alt="img"><h2 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h2><p>编写测试类代码（<code>cn.imzjw.test.AccountServiceTest.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountServiceTest</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取容器</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 业务层接口</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> IAccountService <span class="title function_">getApplicationContext</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">ApplicationContext</span> <span class="variable">ac</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;bean.xml&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> ac.getBean(<span class="string">&quot;accountService&quot;</span>, IAccountService.class);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testFindAll</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 获取容器 --&gt; 得到业务层对象 --&gt; 执行方法</span></span><br><span class="line">        getApplicationContext().findAllAccount().forEach(s -&gt; System.out.println(s));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testFindOne</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(getApplicationContext().findAccountById(<span class="number">1</span>));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testSave</span><span class="params">()</span> &#123;</span><br><span class="line">        getApplicationContext().saveAccount(<span class="keyword">new</span> <span class="title class_">Account</span>(<span class="literal">null</span>, <span class="string">&quot;fff&quot;</span>, <span class="number">1000f</span>));</span><br><span class="line">        testFindAll();</span><br><span class="line">        System.out.println(<span class="string">&quot;---保存成功---&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testUpdate</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 先获取要修改 account 的 id</span></span><br><span class="line">        <span class="type">Account</span> <span class="variable">account</span> <span class="operator">=</span> getApplicationContext().findAccountById(<span class="number">3</span>);</span><br><span class="line">        <span class="comment">// 更新信息</span></span><br><span class="line">        account.setMoney(<span class="number">1234f</span>);</span><br><span class="line">        <span class="comment">// 执行修改</span></span><br><span class="line">        getApplicationContext().updateAccount(account);</span><br><span class="line">        <span class="comment">// 修改完成调用查询所有方法 查看是否修改成功</span></span><br><span class="line">        testFindAll();</span><br><span class="line">        System.out.println(<span class="string">&quot;---修改成功---&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testDelete</span><span class="params">()</span> &#123;</span><br><span class="line">        getApplicationContext().delAccount(<span class="number">4</span>);</span><br><span class="line">        testFindAll();</span><br><span class="line">        System.out.println(<span class="string">&quot;---删除成功---&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>查询所有运行结果为：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Account(id=<span class="number">1</span>, name=aaa, money=<span class="number">1000.0</span>)</span><br><span class="line">Account(id=<span class="number">2</span>, name=bbb, money=<span class="number">1000.0</span>)</span><br><span class="line">Account(id=<span class="number">3</span>, name=ccc, money=<span class="number">1234.0</span>)</span><br></pre></td></tr></table></figure><p>查询一个运行结果为：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Account(id=<span class="number">1</span>, name=aaa, money=<span class="number">1000.0</span>)</span><br></pre></td></tr></table></figure><p>保存账户运行结果为：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Account(id=<span class="number">1</span>, name=aaa, money=<span class="number">1000.0</span>)</span><br><span class="line">Account(id=<span class="number">2</span>, name=bbb, money=<span class="number">1000.0</span>)</span><br><span class="line">Account(id=<span class="number">3</span>, name=ccc, money=<span class="number">1234.0</span>)</span><br><span class="line">Account(id=<span class="number">8</span>, name=ggg, money=<span class="number">1000.0</span>)</span><br><span class="line">---添加成功---</span><br></pre></td></tr></table></figure><p>更新账户运行结果为：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Account(id=<span class="number">1</span>, name=aaa, money=<span class="number">1000.0</span>)</span><br><span class="line">Account(id=<span class="number">2</span>, name=bbb, money=<span class="number">1000.0</span>)</span><br><span class="line">Account(id=<span class="number">3</span>, name=ccc, money=<span class="number">1234.0</span>)</span><br><span class="line">Account(id=<span class="number">8</span>, name=ggg, money=<span class="number">1000.0</span>)</span><br><span class="line">---修改成功---</span><br></pre></td></tr></table></figure><p>删除账户运行结果为：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Account(id=<span class="number">1</span>, name=aaa, money=<span class="number">1000.0</span>)</span><br><span class="line">Account(id=<span class="number">2</span>, name=bbb, money=<span class="number">1000.0</span>)</span><br><span class="line">Account(id=<span class="number">3</span>, name=ccc, money=<span class="number">1234.0</span>)</span><br><span class="line">---删除成功---</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">1.导入maven依赖（pom.xml）2.创建数据库 3.编写实体类（cn.imzjw.entity.Account.java）4.编写持久层代码（cn.imzjw.dao.IAccountDao.java）5.编写业务层代码（cn.imzjw.service.IAccountService.java）</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring" scheme="https://blog.imzjw.cn/tags/Spring/"/>
    
  </entry>
  
  <entry>
    <title>使用 Spring 的 IOC 解决程序耦合</title>
    <link href="https://blog.imzjw.cn/posts/e297092c/"/>
    <id>https://blog.imzjw.cn/posts/e297092c/</id>
    <published>2021-01-18T07:57:25.000Z</published>
    <updated>2021-01-18T07:57:25.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="案例的前期准备"><a href="#案例的前期准备" class="headerlink" title="案例的前期准备"></a>案例的前期准备</h2><p>本文使用的案例是账户的业务层和持久层的依赖关系解决。在开始 spring 的配置之前，我们要先准备一下环境。</p><p>由于我们是使用 spring 解决依赖关系，并不是真正的要做增删改查操作，所以此时我们没必要写实体类。</p><p>创建普通的 Maven 工程</p><p>导入 spring 依赖（ pom.xml ）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-context<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.2.12.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><p>创建业务层接口</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">IAccountService</span> &#123;</span><br><span class="line">  </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 模拟保存账户</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">saveAccount</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>创建业务层接口的实现类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">IAccountService</span> &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 此处的依赖关系有待解决</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">IAccountDao</span> <span class="variable">accountDao</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AccountDaoImpl</span>();</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">saveAccount</span><span class="params">()</span> &#123;</span><br><span class="line">        accountDao.saveAccount();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>创建持久层接口</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">IAccountDao</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 模拟保存账号</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">saveAccount</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>创建持久层接口的实现类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountDaoImpl</span> <span class="keyword">implements</span> <span class="title class_">IAccountDao</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">saveAccount</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;保存成功..&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="基于-XML-的配置"><a href="#基于-XML-的配置" class="headerlink" title="基于 XML 的配置"></a>基于 XML 的配置</h2><p>在 <code>resources</code> 下 new 一个 xml </p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e297092c/c249a2dd648c9b7600be1c8704794c9a.webp" alt="img"></p><p>让 spring 管理资源，在配置文件中配置 <code>service</code> 和 <code>dao</code></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/beans/spring-beans.xsd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- bean 标签：用于配置让 spring 创建对象，并且存入 ioc 容器之中</span></span><br><span class="line"><span class="comment">         id 属性：对象的唯一标识。</span></span><br><span class="line"><span class="comment">         class 属性：指定要创建对象的全限定类名 --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--service层--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;accountService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;cn.imzjw.service.impl.AccountServiceImpl&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--dao层--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;accountDao&quot;</span> <span class="attr">class</span>=<span class="string">&quot;cn.imzjw.dao.impl.AccountDaoImpl&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure><p>测试配置是否成功</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Client</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使用 main 方法获取容器测试执行</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> args</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 1. 使用 ApplicationContext 接口，就是在获取 spring 容器</span></span><br><span class="line">        <span class="type">ApplicationContext</span> <span class="variable">ac</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;bean.xml&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 2. 根据 bean 的 id 获取对象</span></span><br><span class="line">        <span class="type">IAccountService</span> <span class="variable">service</span> <span class="operator">=</span> ac.getBean(<span class="string">&quot;accountService&quot;</span>, IAccountService.class);</span><br><span class="line">        System.out.println(service);</span><br><span class="line"></span><br><span class="line">        <span class="type">IAccountDao</span> <span class="variable">dao</span> <span class="operator">=</span> (IAccountDao) ac.getBean(<span class="string">&quot;accountDao&quot;</span>);</span><br><span class="line">        System.out.println(dao);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cn.imzjw.service.impl.AccountServiceImpl@5688764c</span><br><span class="line">cn.imzjw.dao.impl.AccountDaoImpl@3092bnnk</span><br></pre></td></tr></table></figure><h2 id="Spring-基于-XML-的-IOC-细节"><a href="#Spring-基于-XML-的-IOC-细节" class="headerlink" title="Spring 基于 XML 的 IOC 细节"></a>Spring 基于 XML 的 IOC 细节</h2><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e297092c/b026f8d1169e2ada93878faac7cb4f2f.webp" alt="img"><div class="tip success faa-horizontal animated"><p>BeanFactory 才是 Spring 容器中的顶层接口。 ApplicationContext 只是它的子接口。</p></div><p><code>BeanFactory</code> 和 <code>ApplicationContext</code> 的区别：</p><ul><li>创建对象的时间点不一样。 <ul><li>ApplicationContext：它在构建核心容器时，创建对象采取的策略是立即加载的方式，也就是说，只要一读取配置文件马上就创建配置文件中的配置的对象</li><li>BeanFactory：它在构建核心容器时，创建对象采取的策略是延迟加载的方式，也就是说，什么时候根据 id 获取对象，什么时候才真正的创建对象</li></ul></li></ul><h3 id="ApplicationContext-接口的实现类"><a href="#ApplicationContext-接口的实现类" class="headerlink" title="ApplicationContext 接口的实现类"></a>ApplicationContext 接口的实现类</h3><ul><li><p><code>ClassPathXmlApplicationContext</code>：它是从类的根路径下加载配置文件。<span class='p red'>推荐使用这种</span> </p></li><li><p><code>FileSystemXmlApplicationContext</code>：它是从磁盘路径上加载配置文件，配置文件可以在磁盘的任意位置。</p><p>例如：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">ApplicationContext</span> <span class="variable">ac</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileSystemXmlApplicationContext</span>(<span class="string">&quot;C:\\Users\\garvey\\Desktop\\bean.xml&quot;</span>);</span><br></pre></td></tr></table></figure></li><li><p><code>AnnotationConfigApplicationContext</code>：当我们使用注解配置容器对象时，需要使用此类来创建 spring 容器。它用来读取注解。</p></li></ul><h3 id="bean-标签和管理对象"><a href="#bean-标签和管理对象" class="headerlink" title="bean 标签和管理对象"></a>bean 标签和管理对象</h3><emp>bean</emp> 标签：用于配置对象让 spring 来创建的。 默认情况下它调用的是类中的<wavy>无参构造函数</wavy>。如果没有<wavy>无参构造函数</wavy>则不能创建成功。 <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;accountService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;cn.imzjw.service.impl.AccountServiceImpl&quot;</span> </span></span><br><span class="line"><span class="tag">      <span class="attr">scope</span>=<span class="string">&quot;singleton&quot;</span> <span class="attr">init-method</span>=<span class="string">&quot;init&quot;</span> <span class="attr">destroy-method</span>=<span class="string">&quot;destroy&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure><p>标签中的属性： </p><ul><li><p>id：给对象在容器中提供一个唯一标识。用于获取对象。 </p></li><li><p>class：指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。</p></li><li><p>scope：指定对象的作用范围。</p><ul><li> singleton：单例的，也是默认值</li><li>prototype：多例的</li><li>request：作用于 WEB 项目中，Spring 创建一个 Bean 的对象，将对象存入到 request 域中</li><li>session：作用于 WEB 项目中，Spring 创建一个 Bean 的对象，将对象存入到 session 域中</li><li>global-session：作用于集群环境的会话范围 (全局会话范围)，当不是集群坏境时，它就是 session</li></ul></li><li><p>init-method：指定类中的初始化方法名称。 </p></li><li><p>destroy-method：指定类中销毁方法名称。</p></li></ul><h3 id="bean-的生命周期"><a href="#bean-的生命周期" class="headerlink" title="bean 的生命周期"></a>bean 的生命周期</h3><div class="tabs" id="bean"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="bean-1">单例对象（singleton）</button><button type="button" class="tab " data-href="bean-2">多例对象（prototype）</button></ul><div class="tab-contents"><div class="tab-item-content active" id="bean-1"><div class="note success flat"><p>一个应用只有一个对象的实例。它的作用范围就是整个引用。 </p></div><ul><li>生命周期： <ul><li>出生：当应用加载，创建容器时，对象就被创建了。 </li><li>活着：只要容器在，对象一直活着。 </li><li>死亡：当应用卸载，销毁容器时，对象就被销毁了。 </li></ul></li></ul></div><div class="tab-item-content" id="bean-2"><div class="note success flat"><p>每次访问对象时，都会重新创建对象实例。 </p></div><ul><li>生命周期<ul><li>出生：当使用对象时，创建新的对象实例。 </li><li>活着：只要对象在使用中，就一直活着。 </li><li>死亡：当对象长时间不用时，被 java 的垃圾回收器回收了。</li></ul></li></ul></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="实例化-Bean-的三种方式"><a href="#实例化-Bean-的三种方式" class="headerlink" title="实例化 Bean 的三种方式"></a>实例化 Bean 的三种方式</h3><div class="tabs" id="bean"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="bean-1">第一种方式</button><button type="button" class="tab " data-href="bean-2">第二种方式</button><button type="button" class="tab " data-href="bean-3">第三种方式</button></ul><div class="tab-contents"><div class="tab-item-content active" id="bean-1"><div class="note success flat"><p>使用默认无参构造函数，在 spring 的配置文件中使用 bean 标签，配置 id 和 class 属性之后，且没有其他属性和标签时，采用的就是默认构造函数创建 bean 对象，此时如果类中没有构造函数，则对象无法创建 </p></div><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;accountService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;cn.imzjw.service.impl.AccountServiceImpl&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="bean-2"><div class="note success flat"><p>使用实例工厂的方法创建对象 (使用某个类中的方法来创建对象，并存入 spring 容器) </p></div><p>首先创建一个工厂类（<emp>假设</emp>该类是存在于 jar 包之中的，我们无法通过修改源码的方式来提供构造函数）</p><p><code>cn.imzjw.factory.InstanceFactory</code></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">InstanceFactory</span> &#123;</span><br><span class="line"></span><br><span class="line">   <span class="comment">/**</span></span><br><span class="line"><span class="comment">    * 模拟一个实例工厂，创建业务层实现类</span></span><br><span class="line"><span class="comment">    * 此工厂创建对象，必须现有工厂实例对象，再调用方法</span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">    <span class="keyword">public</span> IAccountService <span class="title function_">getAccountService</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">AccountServiceImpl</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>作用就是使用 <code>InstanceFactory</code> 类中的 <code>getAccountService</code> 方法来创建对象，并存入 spring 容器</p><p>此时 xml 就应该这样写</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;instanceFactory&quot;</span> <span class="attr">class</span>=<span class="string">&quot;cn.imzjw.factory.InstanceFactory&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;accountService&quot;</span> <span class="attr">factory-bean</span>=<span class="string">&quot;instanceFactory&quot;</span> <span class="attr">factory-method</span>=<span class="string">&quot;getAccountService&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure><ul><li>id：指定 bean 的 id，用于从容器中获取</li><li>class：指定实例工厂的全限定类名</li><li>factory-bean：用于指定实例工厂 bean 的 id</li><li>factory-method：用于指定实例工厂中创建对象的方法</li></ul></div><div class="tab-item-content" id="bean-3"><div class="note success flat"><p>使用工厂中的静态方法创建对象（使用某个类中的静态方法创建对象，并存入 spring 容器）</p></div><p>还是一样，创建个类，使用工厂中的静态方法来创建对象</p><p><code>cn.imzjw.factory.StaticFactory</code></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">StaticFactory</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> IAccountService <span class="title function_">getAccountService</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">AccountServiceImpl</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>xml</code></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;accountService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;cn.imzjw.factory.StaticFactory&quot;</span> </span></span><br><span class="line"><span class="tag">      <span class="attr">factory-method</span>=<span class="string">&quot;getAccountService&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure><ul><li>id：指定 bean 的 id，用于从容器中获取 </li><li>class：指定静态工厂的全限定类名 </li><li>factory-method：指定生产对象的静态方法</li></ul></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="spring-的依赖注入"><a href="#spring-的依赖注入" class="headerlink" title="spring 的依赖注入"></a>spring 的依赖注入</h2><p>依赖注入（<code>Dependency Injection</code>）</p><p>它是 spring 框架核心 IOC 的具体实现。 我们的程序在编写时，通过控制反转，把对象的创建交给了 spring，但是代码中不可能出现没有依赖的情况。 IOC 解耦只是降低他们的依赖关系，但不会消除。</p><p>例如：我们的业务层仍会调用持久层的方法。 那这种业务层和持久层的依赖关系，在使用 spring 之后，就让 spring 来维护了。 简单的说，就是坐等框架把持久层对象传入业务层，而不用我们自己去获取。</p><div class="tabs" id="bean"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="bean-1">构造函数注入</button><button type="button" class="tab " data-href="bean-2">set 方法注入</button><button type="button" class="tab " data-href="bean-3">p名称空间注入</button><button type="button" class="tab " data-href="bean-4">集合属性注入</button></ul><div class="tab-contents"><div class="tab-item-content active" id="bean-1"><div class="note success flat"><p>顾名思义，就是使用类中的构造函数，给成员变量赋值。</p></div><div class="note danger flat"><p>注意：赋值的操作不是我们自己做的，而是通过配置的方式，让 spring 框架来为我们注入。</p></div><p>具体代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">IAccountService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 如果是经常变化的数据，并不适用于构造函数注入的方式</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line">    <span class="keyword">private</span> Date date;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">AccountServiceImpl</span><span class="params">(String name, Integer age, Date date)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">        <span class="built_in">this</span>.age = age;</span><br><span class="line">        <span class="built_in">this</span>.date = date;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">saveAccount</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;name=&quot;</span> + name + <span class="string">&quot;, age=&quot;</span> + age + <span class="string">&quot;, date=&quot;</span> + date);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在<code>xml</code>中涉及的标签为<code>constructor-arg</code>，出现的位置在 <code>bean</code> 标签的内部</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;accountService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.itheima.service.impl.AccountServiceImpl&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;张三&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">constructor-arg</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span> <span class="attr">value</span>=<span class="string">&quot;18&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">constructor-arg</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">name</span>=<span class="string">&quot;date&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;now&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">constructor-arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;now&quot;</span> <span class="attr">class</span>=<span class="string">&quot;java.util.Date&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure><p>标签中的属性：</p><ul><li>type：指定参数在构造函数中的数据类型</li><li>index：指定参数在构造函数参数列表的索引位置，参数索引的位置是从 0 开始</li><li>name：指定参数在构造函数中的名称 （<span class='p red'>更常用</span>）⭐</li></ul><p>============以上三个都是找给谁赋值的，下面两个指的是赋什么值的=================</p><ul><li>它能赋的值是基本数据类型和 String 类型</li><li>用于指定其他的 bean 类型数据，指的就是在 spring 的 ioc 核心容器中出现过的 bean 对象</li></ul><p>在main方法中测试运行</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">    <span class="type">ApplicationContext</span> <span class="variable">ac</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;bean.xml&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="type">IAccountService</span> <span class="variable">service</span> <span class="operator">=</span> ac.getBean(<span class="string">&quot;accountService&quot;</span>, IAccountService.class);</span><br><span class="line"></span><br><span class="line">    service.saveAccount();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">name=张三, age=<span class="number">18</span>, date=Mon Jan <span class="number">18</span> <span class="number">18</span>:<span class="number">13</span>:<span class="number">00</span> CST <span class="number">2021</span></span><br></pre></td></tr></table></figure><p>构造函数注入的优势与弊端：</p><div class="note success flat"><p>优势：在获取 bean 对象时，注入数据是必须的，否则对象无法创建成功。</p></div><div class="note warning flat"><p>弊端：改变了 bean 对象的实例化方式，使我们在创建对象时如果用不到这些数据也必须提供。</p></div></div><div class="tab-item-content" id="bean-2"><div class="note success flat"><p>顾名思义，就是在类中提供需要注入成员的 set 方法。</p></div><p>重新 new 一个类取名为 <code>AccountServiceImpl2</code></p><p>具体代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountServiceImpl2</span> <span class="keyword">implements</span> <span class="title class_">IAccountService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line">    <span class="keyword">private</span> Date date;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(String name)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setAge</span><span class="params">(Integer age)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setDate</span><span class="params">(Date date)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.date = date;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">saveAccount</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;name=&quot;</span> + name + <span class="string">&quot;, age=&quot;</span> + age + <span class="string">&quot;, date=&quot;</span> + date);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在<code>xml</code>中涉及的标签为<code>property</code>，出现的位置在 <code>bean</code> 标签的内部</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;accountService2&quot;</span> <span class="attr">class</span>=<span class="string">&quot;cn.imzjw.service.impl.AccountServiceImpl2&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;李四&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span> <span class="attr">value</span>=<span class="string">&quot;22&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;date&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;now&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;now&quot;</span> <span class="attr">class</span>=<span class="string">&quot;java.util.Date&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure><p>标签中的属性：</p><ul><li>name：用于指定注入时所调用的 set 方法名称</li><li>value：用于给属性赋值基本数据类型或者 String 类型</li><li>ref：用于指定其他的 bean 类型数据，指的就是在 spring 的 ioc 核心容器中出现过的 bean 对象</li></ul><p>实际开发中，此方式用的较多。⭐</p><p>在main方法中测试运行</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">    <span class="type">ApplicationContext</span> <span class="variable">ac</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;bean.xml&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="type">IAccountService</span> <span class="variable">service</span> <span class="operator">=</span> ac.getBean(<span class="string">&quot;accountService2&quot;</span>, IAccountService.class);</span><br><span class="line"></span><br><span class="line">    service.saveAccount();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">name=李四, age=<span class="number">22</span>, date=Mon Jan <span class="number">18</span> <span class="number">18</span>:<span class="number">25</span>:<span class="number">21</span> CST <span class="number">2021</span></span><br></pre></td></tr></table></figure><div class="note success flat"><p>优势：创建对象时没有明确的限制，可以直接使用构造函数。</p></div><div class="note warning flat"><p>弊端：如果某个成员必须有值，则获取对象有可能 set 方法没有执行。</p></div></div><div class="tab-item-content" id="bean-3"><div class="note success flat"><p>此方式是通过在 xml 中导入 p 名称空间，使用 <code>p:propertyName</code> 来注入数据，它的本质仍然是调用类中的 set 方法实现注入功能。</p></div><p>new一个类取名为 <code>AccountServiceImpl3</code></p><p>具体代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 使用 p 名称空间注入，本质还是调用类中的 set 方法</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountServiceImpl3</span> <span class="keyword">implements</span> <span class="title class_">IAccountService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line">    <span class="keyword">private</span> Date date;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(String name)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setAge</span><span class="params">(Integer age)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setDate</span><span class="params">(Date date)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.date = date;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">saveAccount</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;name=&quot;</span> + name + <span class="string">&quot;, age=&quot;</span> + age + <span class="string">&quot;, date=&quot;</span> + date);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>使用了p名称空间注入的方式需给配置文件导入约束</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xmlns:p=&quot;http://www.springframework.org/schema/p&quot;</span><br></pre></td></tr></table></figure><p><code>xml</code>代码如下</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:p</span>=<span class="string">&quot;http://www.springframework.org/schema/p&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/beans/spring-beans.xsd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;accountService3&quot;</span> <span class="attr">class</span>=<span class="string">&quot;cn.imzjw.service.impl.AccountServiceImpl3&quot;</span> </span></span><br><span class="line"><span class="tag">          <span class="attr">p:name</span>=<span class="string">&quot;王五&quot;</span> <span class="attr">p:age</span>=<span class="string">&quot;23&quot;</span> <span class="attr">p:date-ref</span>=<span class="string">&quot;now&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;now&quot;</span> <span class="attr">class</span>=<span class="string">&quot;java.util.Date&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure><p>在main方法中测试运行</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">    <span class="type">ApplicationContext</span> <span class="variable">ac</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;bean.xml&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="type">IAccountService</span> <span class="variable">service</span> <span class="operator">=</span> ac.getBean(<span class="string">&quot;accountService3&quot;</span>, IAccountService.class);</span><br><span class="line"></span><br><span class="line">    service.saveAccount();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">name=王五, age=<span class="number">23</span>, date=Mon Jan <span class="number">18</span> <span class="number">18</span>:<span class="number">34</span>:<span class="number">52</span> CST <span class="number">2021</span></span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="bean-4"><div class="note success flat"><p>顾名思义，就是给类中的集合成员传值，它用的也是set方法注入的方式，只不过变量的数据类型都是集合。</p></div> <p>我们这里注入List、Set、Map、Properties</p><p>new一个类取名为 <code>AccountServiceImpl4</code></p><p>具体代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountServiceImpl4</span> <span class="keyword">implements</span> <span class="title class_">IAccountService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String[] str;</span><br><span class="line">    <span class="keyword">private</span> List&lt;String&gt; list;</span><br><span class="line">    <span class="keyword">private</span> Set&lt;String&gt; set;</span><br><span class="line">    <span class="keyword">private</span> Map&lt;String, String&gt; map;</span><br><span class="line">    <span class="keyword">private</span> Properties prop;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setStr</span><span class="params">(String[] str)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.str = str;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setList</span><span class="params">(List&lt;String&gt; list)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.list = list;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setSet</span><span class="params">(Set&lt;String&gt; set)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.set = set;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setMap</span><span class="params">(Map&lt;String, String&gt; map)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.map = map;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setProp</span><span class="params">(Properties prop)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.prop = prop;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">saveAccount</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;str=&quot;</span> + Arrays.toString(str) + <span class="string">&quot;, list=&quot;</span> + list + <span class="string">&quot;, set=&quot;</span> + set + <span class="string">&quot;, map=&quot;</span> + map + <span class="string">&quot;, prop=&quot;</span> + prop);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>xml</code></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:p</span>=<span class="string">&quot;http://www.springframework.org/schema/p&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/beans/spring-beans.xsd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;accountService4&quot;</span> <span class="attr">class</span>=<span class="string">&quot;cn.imzjw.service.impl.AccountServiceImpl4&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--数组--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;str&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">array</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">value</span>&gt;</span>小嘉<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">value</span>&gt;</span>是真的<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">value</span>&gt;</span>帅啊<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">array</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- List --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;list&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">list</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">value</span>&gt;</span>我是<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">value</span>&gt;</span>list<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">list</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- Set --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;set&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">set</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">value</span>&gt;</span>我是<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">value</span>&gt;</span>set<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">set</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- Map --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;map&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">map</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">entry</span> <span class="attr">key</span>=<span class="string">&quot;小嘉&quot;</span> <span class="attr">value</span>=<span class="string">&quot;是真的帅啊&quot;</span>/&gt;</span></span><br><span class="line">                <span class="comment">&lt;!--另一种写法--&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">entry</span> <span class="attr">key</span>=<span class="string">&quot;我真的喜欢&quot;</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">value</span>&gt;</span>小嘉<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">entry</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">map</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- Properties --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;prop&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">props</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">prop</span> <span class="attr">key</span>=<span class="string">&quot;小嘉&quot;</span>&gt;</span>真的帅啊<span class="tag">&lt;/<span class="name">prop</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">prop</span> <span class="attr">key</span>=<span class="string">&quot;我是&quot;</span>&gt;</span>Properties<span class="tag">&lt;/<span class="name">prop</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">props</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure><div class="tip bell"><p>在注入集合数据时，只要结构相同，标签可以互换，例如：</p></div><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;accountService3&quot;</span> <span class="attr">class</span>=<span class="string">&quot;cn.imzjw.service.impl.AccountServiceImpl3&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--数组更改了 list 标签--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;str&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">list</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">value</span>&gt;</span>小嘉<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">value</span>&gt;</span>是真的<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">value</span>&gt;</span>帅啊<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">list</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- List 更改了 array 标签 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;list&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">array</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">value</span>&gt;</span>我是<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">value</span>&gt;</span>list<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">array</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- Set 更改了 list 标签 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;set&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">list</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">value</span>&gt;</span>我是<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">value</span>&gt;</span>set<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">list</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- Map 更改了 props 标签 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;map&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">props</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">prop</span> <span class="attr">key</span>=<span class="string">&quot;小嘉&quot;</span>&gt;</span>真的帅啊<span class="tag">&lt;/<span class="name">prop</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">prop</span> <span class="attr">key</span>=<span class="string">&quot;我是&quot;</span>&gt;</span>Properties<span class="tag">&lt;/<span class="name">prop</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">props</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- Properties 更改了 map 标签--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;prop&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">map</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">entry</span> <span class="attr">key</span>=<span class="string">&quot;小嘉&quot;</span> <span class="attr">value</span>=<span class="string">&quot;是真的帅啊&quot;</span>/&gt;</span></span><br><span class="line">            <span class="comment">&lt;!--另一种写法--&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">entry</span> <span class="attr">key</span>=<span class="string">&quot;我真的喜欢&quot;</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">value</span>&gt;</span>小嘉<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">entry</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">map</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure><p>在main方法中测试运行</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">    <span class="type">ApplicationContext</span> <span class="variable">ac</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;bean.xml&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="type">IAccountService</span> <span class="variable">service</span> <span class="operator">=</span> ac.getBean(<span class="string">&quot;accountService4&quot;</span>, IAccountService.class);</span><br><span class="line"></span><br><span class="line">    service.saveAccount();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行结果：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">str=[小嘉, 是真的, 帅啊], list=[我是, list], set=[我是, set], map=&#123;我是=Properties, 小嘉=真的帅啊&#125;, prop=&#123;我真的喜欢=小嘉, 小嘉=是真的帅啊&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div>]]></content>
    
    
    <summary type="html">本文使用的案例是账户的业务层和持久层的依赖关系解决。在开始 spring 的配置之前，我们要先准备一下环境。由于我们是使用 spring 解决依赖关系，并不是真正的要做增删改查操作，所以此时我们没必要写实体类。</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring" scheme="https://blog.imzjw.cn/tags/Spring/"/>
    
  </entry>
  
  <entry>
    <title>Spring 复习 - IOC 的概念和作用</title>
    <link href="https://blog.imzjw.cn/posts/77bbf9f1/"/>
    <id>https://blog.imzjw.cn/posts/77bbf9f1/</id>
    <published>2021-01-17T08:41:59.000Z</published>
    <updated>2021-01-17T08:41:59.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="什么是程序的耦合"><a href="#什么是程序的耦合" class="headerlink" title="什么是程序的耦合"></a>什么是程序的耦合</h2><p>耦合性（Coupling） 也叫耦合度，是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系，包括控制关系、调用关系、数据传递关系。模块间联系越多，其耦合性越强，同时表明其独立性越差( 降低耦合性，可以提高其独立性)。耦合性存在于各个领域，而非软件设计中独有的，但是我们只讨论软件工程中的耦合。 在软件工程中，耦合指的就是就是对象之间的依赖性。对象之间的耦合越高，维护成本越高。因此对象的设计应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则就是高内聚低耦合。</p><p>它有如下分类</p><ol><li>内容耦合。当一个模块直接修改或操作另一个模块的数据时，或一个模块不通过正常入口而转入另一个模块时，这样的耦合被称为内容耦合。内容耦合是最高程度的耦合，应该避免使用。</li><li>公共耦合。两个或两个以上的模块共同引用一个全局数据项，这种耦合被称为公共耦合。在具有大量公共耦合的结构中，确定究竟是哪个模块给全局变量赋了一个特定的值是十分困难的。</li><li>外部耦合 。一组模块都访问同一全局简单变量而不是同一全局数据结构，而且不是通过参数表传 递该全局变量的信息，则称之为外部耦合。</li><li>控制耦合 。一个模块通过接口向另一个模块传递一个控制信号，接受信号的模块根据信号值而进 行适当的动作，这种耦合被称为控制耦合。</li><li>标记耦合 。若一个模块 A 通过接口向两个模块 B 和 C 传递一个公共参数，那么称模块 B 和 C 之间存在一个标记耦合。</li><li>数据耦合。模块之间通过参数来传递数据，那么被称为数据耦合。数据耦合是最低的一种耦合形式，系统中一般都存在这种类型的耦合，因为为了完成一些有意义的功能，往往需要将某些模块的输出数据作为另一些模块的输入数据。</li><li>非直接耦合 。两个模块之间没有直接关系，它们之间的联系完全是通过主模块的控制和调用来实现的。</li></ol><p><strong>总结：</strong>耦合是影响软件复杂程度和设计质量的一个重要因素，在设计上我们应采用以下原则：</p><div class="note success flat"><p>如果模块间必须存在耦合，就尽量使用数据耦合，少用控制耦合，限制公共耦合的范围，尽量避免使用内容耦合。</p></div><h3 id="内聚与耦合"><a href="#内聚与耦合" class="headerlink" title="内聚与耦合"></a>内聚与耦合</h3><p>内聚标志一个模块内各个元素彼此结合的紧密程度，它是信息隐蔽和局部化概念的自然扩展，内聚是从功能角度来度量模块内的联系，一个好的内聚模块应当恰好做一件事。它描述的是模块内的功能联系。</p><p>耦合是软件结构中各模块之间相互连接的一种度量，耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据。 程序讲究的是低耦合，高内聚。就是同一个模块内的各个元素之间要高度紧密，但是各个模块之 间的相互依存度却要不那么紧密。 内聚和耦合是密切相关的，同其他模块存在高耦合的模块意味着低内聚，而高内聚的模块意味着该模块同其他模块之间是低耦合。</p><p>在进行软件设计时，应力争做到 <span class='p red'>高内聚</span>，<span class='p cyan'>低耦合。</span></p><h3 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h3><p>我们在开发中，有些依赖关系是必须的，有些依赖关系可以通过优化代码来解除的。</p><p>示例代码：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">IAccountService</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">IAccountDao</span> <span class="variable">accountDao</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AccountDaoImpl</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>上面的代码表示： 业务层调用持久层，并且此时业务层在依赖持久层的接口和实现类。如果此时没有持久层实现类，编译将不能通过。这种编译期依赖关系，应该在我们开发中杜绝。我们需要优化代码解决。</p><p>再比如：早期我们的 JDBC 操作，注册驱动时，我们为什么不使用 DriverManager 的 register 方法，而是采用 Class.forName 的方式？</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">JdbcDemo1</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="comment">// 1.注册驱动</span></span><br><span class="line">        <span class="comment">// DriverManager.registerDriver(new com.mysql.jdbc.Driver());</span></span><br><span class="line">        Class.forName(<span class="string">&quot;com.mysql.jdbc.Driver&quot;</span>);</span><br><span class="line">        <span class="comment">// 2.获取连接</span></span><br><span class="line">        <span class="comment">// 3.获取预处理 sql 语句对象</span></span><br><span class="line">        <span class="comment">// 4.获取结果集</span></span><br><span class="line">        <span class="comment">// 5.遍历结果集</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>原因就是： 我们的类依赖了数据库的具体驱动类（MySQL），如果这时候更换了数据库品牌（比如 Oracle），那么就需要修改源码来重新数据库驱动。这显然不是我们想要的。</p><h3 id="解决程序耦合的思路"><a href="#解决程序耦合的思路" class="headerlink" title="解决程序耦合的思路"></a>解决程序耦合的思路</h3><p>原来是通过反射来注册驱动的</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Class.forName(<span class="string">&quot;com.mysql.jdbc.Driver&quot;</span>);</span><br></pre></td></tr></table></figure><p>此时的好处就是我们的类中不再依赖具体的驱动类，此时就算删除 mysql 的驱动 jar 包，依然可以编译（运行就不要想了，没有驱动不可能运行成功的）</p><p> 同时，也产生了一个新的问题，mysql 驱动的全限定类名字符串是在 java 类中写死的，一旦要改还是要修改源码。 解决这个问题也很简单，使用配置文件配置。</p><h3 id="工厂模式解耦"><a href="#工厂模式解耦" class="headerlink" title="工厂模式解耦"></a>工厂模式解耦</h3><p>在实际开发中我们可以把三层的对象都使用配置文件配置起来，当启动服务器应用加载的时候，让一个类中的方法通过读取配置文件，把这些对象创建出来并存起来。在接下来的使用的时候，直接拿过来用就好了。 那么，这个读取配置文件、创建和获取三层对象的类就是工厂。</p><h3 id="控制反转（IOC）"><a href="#控制反转（IOC）" class="headerlink" title="控制反转（IOC）"></a>控制反转（IOC）</h3><p>上一小节解耦的思路有 2 个问题</p><ol><li><p>存哪去？ 分析：由于我们是很多对象，肯定要找个集合来存。这时候有 Map 和 List 供选择。 到底选 Map 还是 List 就看我们有没有查找需求。有查找需求，选 Map。 所以我们的答案就是在应用加载时，创建一个 Map，用于存放三层对象。我们把这个 map 称之为容器。</p></li><li><p>还是没解释什么是工厂？ 工厂就是负责给我们从容器中获取指定对象的类。这时候我们获取对象的方式发生了改变。 </p><p>原来： 我们在获取对象时，都是采用 new 的方式。是主动的。</p><p>现在： 我们获取对象时，同时跟工厂要，有工厂为我们查找或者创建对象。是被动的。</p></li></ol><div class="tip cogs"><p>这种被动接收的方式获取对象的思想就是控制反转，它是 spring 框架的核心之一。</p></div><p>其作用就是削减计算机程序的耦合（解除我们代码中的依赖关系）</p>]]></content>
    
    
    <summary type="html">耦合性（Coupling） 也叫耦合度，是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系，包括控制关系、调用关系、数据传递关系。</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring" scheme="https://blog.imzjw.cn/tags/Spring/"/>
    
  </entry>
  
  <entry>
    <title>Spring 复习 - 概述</title>
    <link href="https://blog.imzjw.cn/posts/3c6aa15/"/>
    <id>https://blog.imzjw.cn/posts/3c6aa15/</id>
    <published>2021-01-17T08:03:50.000Z</published>
    <updated>2021-01-17T08:03:50.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="spring是什么"><a href="#spring是什么" class="headerlink" title="spring是什么"></a>spring是什么</h2><p>Spring 是分层的 Java SE/EE 应用 <code>full-stack</code> 轻量级开源框架，以 <code>IOC（Inverse Of Control）</code> 反转控制 和 <code>AOP（Aspect Oriented Programming）</code>面向切面编程为内核，提供了展现层 Spring MVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术，还能整合开源世界众多著名的第三方框架和类库，逐渐成为使用最多的 Java EE 企业应用开源框架。</p><h2 id="Spring-的发展历程"><a href="#Spring-的发展历程" class="headerlink" title="Spring 的发展历程"></a>Spring 的发展历程</h2><ul><li>1997 年 IBM 提出了 EJB 的思想 </li><li>1998 年 SUN 制定开发标准规范 EJB1.0 </li><li>1999 年 EJB1.1 发布 </li><li>2001 年 EJB2.0 发布 </li><li>2003 年 EJB2.1 发布 </li><li>2006 年 EJB3.0 发布 </li></ul><div class="btns circle grid5">            <a class="button" href='https://en.wikipedia.org/wiki/Rod_Johnson_(programmer)' title='Rod Johnson（Spring之父）'><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src='https://bu.dusays.com/2021/01/17/9b14406667d8c.png'>Rod Johnson（Spring之父）</a>          </div><ul><li>Expert One-to-One J2EE Design and Development (2002) <ul><li>阐述了 J2EE 使用 EJB 开发设计的优点及解决方案 </li></ul></li><li>Expert One-to-One J2EE Development without EJB (2004) <ul><li>阐述了 J2EE 开发不使用 EJB 的解决方式（Spring 雏形） 2017 年 9 月份发布了 spring 的最新版本 spring 5.0 通用版（GA） </li></ul></li></ul><h2 id="spring-的优势"><a href="#spring-的优势" class="headerlink" title="spring 的优势"></a>spring 的优势</h2><ol><li>方便解耦，简化开发<ul><li>通过 Spring 提供的 IoC 容器，可以将对象间的依赖关系交由 Spring 进行控制，避免硬编码所造 成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码，可 以更专注于上层的应用。 </li></ul></li><li>AOP 编程的支持<ul><li>通过 Spring 的 AOP 功能，方便进行面向切面的编程，许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松应付。</li></ul></li><li>声明式事务的支持<ul><li>可以将我们从单调烦闷的事务管理代码中解脱出来，通过声明式方式灵活的进行事务的管理， 提高开发效率和质量。</li></ul></li><li>方便程序的测试<ul><li>可以用非容器依赖的编程方式进行几乎所有的测试工作，测试不再是昂贵的操作，而是随手可做的事情。</li></ul></li><li>方便集成各种优秀框架<ul><li>Spring 可以降低各种框架的使用难度，提供了对各种优秀框架（Struts、Hibernate、Hessian、Quartz 等）的直接支持。</li></ul></li><li> 降低 JavaEE API 的使用难度</li></ol><ul><li>Spring 对 JavaEE API（如 JDBC、JavaMail、远程调用等）进行了薄薄的封装层，使这些 API 的 使用难度大为降低。</li></ul><ol start="7"><li> Java 源码是经典学习范例</li></ol><ul><li>Spring 的源代码设计精妙、结构清晰、匠心独用，处处体现着大佬对 Java 设计模式灵活运用以及对 Java 技术的高深造诣。它的源代码无疑是 Java 技术的最佳实践的范例。</li></ul><h2 id="spring-的体系结构"><a href="#spring-的体系结构" class="headerlink" title="spring 的体系结构"></a>spring 的体系结构</h2><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/3c6aa15/7a340ece735a8fe8072dc73bbeb6f693.webp" alt="图片来自 https://docs.spring.io/"></p>]]></content>
    
    
    <summary type="html">Spring 是分层的 Java SE/EE 应用 full-stack轻量级开源框架，以 IOC（Inverse Of Control）反转控制 和 AOP（Aspect Oriented Programming）面向切面编程为内核</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring" scheme="https://blog.imzjw.cn/tags/Spring/"/>
    
  </entry>
  
  <entry>
    <title>利用 Github Actions 每天定时自动签到贴吧</title>
    <link href="https://blog.imzjw.cn/posts/actions-tieba/"/>
    <id>https://blog.imzjw.cn/posts/actions-tieba/</id>
    <published>2021-01-10T13:27:16.000Z</published>
    <updated>2021-03-25T02:15:22.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>此开源项目用的是手机端的接口，签到经验更多，只需要在 <code>secrets</code> 中填写 <code>BDUSS</code> 即可，每天自动帮你签到，最多支持 <code>200</code> 个贴吧签到。</p><p><strong>关于安全问题：</strong></p><p>此项目每一轮性将所有未签到的贴吧进行签到，一共进行 5 轮，如果还未签到完就立即结束</p><p>为了减少接口访问次数，每一轮签到完等待 1 分钟，如果在过程中所有贴吧签到完则结束。</p><p>所以不用担心啥啥啥的，我用了三个多月了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/actions-tieba/images.745rdu4z2ss0.webp" alt="images"></p><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><ol><li><p>fork 项目，此项目是基于 <a href="https://github.com/srcrs/TiebaSignIn">TiebaSignIn</a>，<del>修改添加 <a href="https://qmsg.zendee.cn/">Qmsg</a> 酱</del> （已取消 Qmsg 酱），<a href="https://t.me/">Telegram</a>  通知</p><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/dajibo/tieba"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=dajibo&repo=tieba&theme=buefy&show_owner=true"/></a></li><li><p>获取 <code>BDUSS</code>，打开浏览器登录 <a href="https://tieba.baidu.com/">贴吧</a>，然后按下 <code>F12</code> 打开调试模式，在 <code>cookie</code> 中找到 <code>BDUSS</code>，并复制其 <code>Value</code> 值</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/actions-tieba/image-20210110214631793.webp" alt="img"></p></li><li><p>将复制的 Value 值扔到仓库的 <code>Secrets</code> 中，并取名为 <code>BDUSS</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/actions-tieba/image-20210110215033800.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/actions-tieba/image-20210110215300284.webp" alt="img"></p></li><li><p>开启 <code>actions</code>，默认 <code>actions</code> 是处于禁止的状态，需要手动开启。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/actions-tieba/image-20210110215554533.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/actions-tieba/image-20210110215634476.webp" alt="img"></p></li><li><p>运行 actions（两种方式供选择）</p><ul><li><p>自己提交一次，然后 push</p></li><li><p>或者将仓库里的 <code>run.txt</code> 中的 <code>flag</code> 由 0 改为 1，然后 commit</p><figure class="highlight patch"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="deletion">- flag: 0</span></span><br><span class="line"><span class="addition">+ flag: 1</span></span><br></pre></td></tr></table></figure><p>接着跑到 Actions 中发现正在开始签到了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/actions-tieba/image-20210110220336536.webp" alt="img"></p><div class="note primary flat"><p>第一次运行成功之后，那么将会在每天早上的 <code>6:30</code> 自动进行贴吧签到</p></div></li></ul></li></ol><h2 id="推送服务（可选）"><a href="#推送服务（可选）" class="headerlink" title="推送服务（可选）"></a>推送服务（可选）</h2><del>此项目目前只有三个服务推送</del><div class="note danger flat"><p>1/14/2021 更新，取消 Server 酱和 Qmsg 酱，只进行 Telegram 推送</p></div><h3 id=""><a href="#" class="headerlink" title=""></a><del>server 酱配置</del></h3><p><del>需在 <code>Secrets</code> 中添加 <a href="https://sc.ftqq.com/">server 酱 </a>的 <code>SCKEY</code>，格式如下</del></p><table><thead><tr><th align="center">Name</th><th align="center">Value</th></tr></thead><tbody><tr><td align="center">SCKEY</td><td align="center">xxxxxxxxxx</td></tr></tbody></table><div class="note warning flat"><p><code>SCKEY</code> 需在 <a href="http://sc.ftqq.com/">server 酱 </a>中获取</p></div><h3 id="-1"><a href="#-1" class="headerlink" title=""></a><del>Qmsg 酱配置</del></h3><p><del>同样需在 <code>Secrets</code> 中添加 <a href="https://qmsg.zendee.cn/">qmsg 酱</a> 的 <code>QMSGKEY</code> ，格式如下</del></p><table><thead><tr><th align="center">Name</th><th align="center">Value</th></tr></thead><tbody><tr><td align="center">QMSGKEY</td><td align="center">xxxxxxxxxx</td></tr></tbody></table><div class="note warning flat"><p><code>QMSGKEY</code>  需在  <a href="https://qmsg.zendee.cn/">qmsg 酱</a> 中获取</p></div><h3 id="Telegram-配置"><a href="#Telegram-配置" class="headerlink" title="Telegram 配置"></a>Telegram 配置</h3><p>Telegram 通知需要用到机器人，创建机器人的教程自行 Google</p><p>需要用到两个参数</p><ol><li>机器人的 TOKEN</li><li>CHAT_ID</li></ol><h4 id="获取机器人-TOKEN"><a href="#获取机器人-TOKEN" class="headerlink" title="获取机器人 TOKEN"></a>获取机器人 TOKEN</h4><p>机器人的 TOKEN 需要在它芭比 <a href="https://t.me/botfather">@BotFather</a> 那里获取</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/actions-tieba/ffd797da113e218da05ff3bb09b315df.webp" alt="img"></p><p>在 <code>Secrets</code> 中添加机器人 Bot 的 <code>Token</code>，格式如下</p><table><thead><tr><th align="center">Name</th><th align="center">Value</th></tr></thead><tbody><tr><td align="center">BOTTOKEN</td><td align="center">xxxx:xxxxxxxxxxx</td></tr></tbody></table><h4 id="CHAT-ID-获取"><a href="#CHAT-ID-获取" class="headerlink" title="CHAT_ID 获取"></a>CHAT_ID 获取</h4><p>有两种方式</p><p>方式一：</p><p>点击 <a href="https://api.telegram.org/bot%7BTOKEN%7D/getUpdates">https://api.telegram.org/bot{TOKEN}/getUpdates</a> 获取与机器人的 <code>chatId</code>（需要用上面获取的机器人 TOKEN 替换进链接里的 {TOKEN} 后访问）</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/actions-tieba/b40cd2384ec8699832d4acbb2c0fa322.webp" alt="img"></p><p>方式二：</p><p>这个比较简单</p><p>点击 <a href="https://t.me/userinfobot">@userinfobot</a> 机器人，随便向他发送几句话即可获取到自己的 <code>chat_id</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/actions-tieba/3deb2d35e627e1b4097e96f7bf656c8b.webp" alt="img"></p><p>最后在 <code>Secrets</code> 中添加 CHAT_ID，格式如下</p><table><thead><tr><th align="center">Name</th><th align="center">Value</th></tr></thead><tbody><tr><td align="center">CHAT_ID</td><td align="center">123456789</td></tr></tbody></table><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/actions-tieba/e49cb8008d0111801580f8387ea06dd9.webp" alt="img"></p><h2 id="推送成功"><a href="#推送成功" class="headerlink" title="推送成功"></a>推送成功</h2><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/actions-tieba/image-20210224211950194.hsmf0xhf13c.webp" alt="success"></p>]]></content>
    
    
      
      
        
        
    <summary type="html"></summary>
        
      
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="GitHub Actions" scheme="https://blog.imzjw.cn/tags/GitHub-Actions/"/>
    
  </entry>
  
  <entry>
    <title>解决 GitHub Actions 自动部署 Hexo 时文章更新日期发生变化</title>
    <link href="https://blog.imzjw.cn/posts/1411ca0e/"/>
    <id>https://blog.imzjw.cn/posts/1411ca0e/</id>
    <published>2021-01-06T09:29:27.000Z</published>
    <updated>2021-03-29T08:15:29.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在你使用了 Github Actions 自动部署 Hexo 时，部署成功之后打开你网站里的文章（指博客内的所有文章），更新日期是否发生变化了呢？</p><p>这是因为使用 Git 管理站点，所以文件的最后更新日期常常会发生改变，虽然没什么影响，但是我看着不舒服</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1411ca0e/image-20210106175509177.webp" alt="img"></p><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><p>我目前知道的有两种方法</p><h3 id="第一种"><a href="#第一种" class="headerlink" title="第一种"></a>第一种</h3><p>在 <code>Front-matter</code> 加个 updated 参数即可</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1411ca0e/image-20210106174011495.webp" alt="img"></p><p>显然，这种方式要在所有文章上加上 updated 属性，很麻烦</p><p>所以我就跑到 <a href="https://hexo.io/">Hexo</a> 官网找来找去，结果还真被我找到了，所以就有了第二种方法！</p><h3 id="第二种（推荐）"><a href="#第二种（推荐）" class="headerlink" title="第二种（推荐）"></a>第二种（推荐）</h3><p>在 Hexo 根目录的配置文件（  <code>_config.yml</code>  ）中，找到 <code>updated_option</code></p><p><code>updated_option</code> 中有三个可选参数</p><ul><li>mtime：使用文件的最后修改时间。这是从 Hexo 3.0.0 开始的默认行为。</li><li>date：使用 <code>date</code> 作为 <code>updated</code> 的值。可被用于 Git 工作流之中，因为使用 Git 管理站点时，文件的最后修改日期常常会发生改变</li><li>empty：直接删除 <code>updated</code>。使用这一选项可能会导致大部分主题和插件无法正常工作</li></ul><p>故我们 <code>updated_option</code> 设为 <code>date</code> 即可</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1411ca0e/image-20210106174925534.webp" alt="img"></p><h2 id="最后"><a href="#最后" class="headerlink" title="最后"></a>最后</h2><p>在您真正要更新文章的时候，就在 <code>Front-matter</code> 加个 updated 参数！</p>]]></content>
    
    
    <summary type="html">在你使用了 Github Actions 自动部署 Hexo 时，部署成功之后打开你网站里的文章（指博客内的所有文章），更新日期是否发生变化了呢？这是因为使用 Git 管理站点，所以文件的最后更新日期常常会发生改变，虽然没什么影响，但是我看着不舒服</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>Spring Boot 自定义通用异常</title>
    <link href="https://blog.imzjw.cn/posts/4d5896c2/"/>
    <id>https://blog.imzjw.cn/posts/4d5896c2/</id>
    <published>2021-01-06T05:25:04.000Z</published>
    <updated>2021-01-06T05:25:04.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>如果一个项目都包含了各种各样的服务。每个服务都又以不同的方式返回异常信息，这样排查的时候就会比较麻烦。如果我们定义一个标准的异常处理体系。并在所有的服务中使用。那样开发起来就可以快速定位。节约时间来摸🐟，并且页面也会更加的简单和直观。</p><p>本文开发环境</p><ul><li><a href="https://docs.spring.io/spring-boot/docs/2.4.1/reference/htmlsingle/">springboot 2.4.1</a></li><li><a href="https://confluence.jetbrains.com/display/IDEADEV/IntelliJ+IDEA+2018.3.6+(183.6156.11+build)+Release+Notes">IntelliJ IDEA 2018.3.6 </a></li></ul><p>本文将会模拟异常</p><div class="note danger flat"><p>案例：查询数据库，发现返回的是 null，就抛出异常。</p></div><h2 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h2><p>new 一个 Springboot 应用</p><p>新建 <code>entity</code> 包，创建 User 实体类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span> <span class="comment">// 注意导Lombok，不然你也可以手动生成getter、setter</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">User</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>new 一个 service 包，创建 UserService</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> User <span class="title function_">getOne</span><span class="params">(<span class="type">int</span> id)</span> &#123;</span><br><span class="line">        <span class="comment">// 模拟异常、向数据库查询User，但是数据库没有，返回null</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里就是模拟发生异常的案例，并没有真正的操作数据库。当调用 getOne 方法时，直接返回 null 就好啦</p><p>new 一个 exception 包，创建 NotFoundException 类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">NotFoundException</span> <span class="keyword">extends</span> <span class="title class_">RuntimeException</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">NotFoundException</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>(message);</span><br><span class="line">        System.out.println(<span class="string">&quot;oh! bad 发生异常啦，异常info：&quot;</span> + message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里自定义了一个异常类继承了 <code>RuntimeException</code>，其作用就是当数据库查询的时候一旦发现返回值为 null，就直接抛出这个异常信息。</p><p>接着 new 一个 controlle r包，创建 UserController 类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> UserService userService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;&#123;id&#125;&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> User <span class="title function_">getUser</span><span class="params">(<span class="meta">@PathVariable</span> <span class="type">int</span> id)</span> <span class="keyword">throws</span> NotFoundException &#123;</span><br><span class="line">        <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> userService.getOne(id);</span><br><span class="line">        <span class="keyword">if</span> (user == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">NotFoundException</span>(<span class="string">&quot;id: &quot;</span> + id);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> user;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后启动 Springboot，浏览器进行访问</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4d5896c2/image-20210106135951109.webp" alt="500"></p><p>可以发现报 <a href="https://www.exai.com/blog/http-error-500-wordpress">500</a> 服务器内部错误，但是你觉得这样好吗，用户看得懂 500 吗，我们项目里没有某个资源或者没有找到的话总不能提示服务器内部错误吧。所以呢，现在要对抛出的异常进行一个处理。</p><h3 id="异常处理"><a href="#异常处理" class="headerlink" title="异常处理"></a>异常处理</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ResponseStatus(HttpStatus.NOT_FOUND)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">NotFoundException</span> <span class="keyword">extends</span> <span class="title class_">RuntimeException</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">NotFoundException</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>(message);</span><br><span class="line">        System.out.println(<span class="string">&quot;oh! bad 发生异常啦，异常info：&quot;</span> + message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在自定义异常类上加一个 @ResponseStatus 的注解来生成 <code>404 Not Found</code> 状态。</p><p>当然还有其他的状态。自己可以点击 HttpStatus 源码详看，根据自己的需要去返回。</p><p>我们使用 <code>HttpStatus.NOT_FOUND</code>，其作用就是用户访问的时候，一旦发生异常就会显示 404 错误。</p><p>启动 Springboot</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4d5896c2/image-20210106141335311.webp" alt="404"></p><p>可以发现不是服务器内部错误了</p><h2 id="通用的异常处理"><a href="#通用的异常处理" class="headerlink" title="通用的异常处理"></a>通用的异常处理</h2><ol><li><p>添加依赖（pom.xml）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-webmvc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.3.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>在 entity 包下创建异常实体类 ExceptionResponse</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ExceptionResponse</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Getter</span></span><br><span class="line">    <span class="keyword">private</span> Date date;</span><br><span class="line">    <span class="meta">@Getter</span></span><br><span class="line">    <span class="keyword">private</span> String msg;</span><br><span class="line">    <span class="meta">@Getter</span></span><br><span class="line">    <span class="keyword">private</span> String requestUrl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里只需要 getter 方法，setter 方法就不需要了，这个类的作用就是当有异常发生时，就把信息展示在页面上</p></li><li><p>在 exception 包下创建通用异常处理类 GeneralEntityExceptionHandler</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ControllerAdvice</span></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GeneralEntityExceptionHandler</span> <span class="keyword">extends</span> <span class="title class_">ResponseEntityExceptionHandler</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">      * 此方法主要处理所有的异常信息(500)</span></span><br><span class="line"><span class="comment">      *</span></span><br><span class="line"><span class="comment">      * <span class="doctag">@param</span> ex</span></span><br><span class="line"><span class="comment">      * <span class="doctag">@param</span> request</span></span><br><span class="line"><span class="comment">      * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">      */</span></span><br><span class="line">    <span class="meta">@ExceptionHandler(Exception.class)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">final</span> ResponseEntity&lt;Object&gt; <span class="title function_">handleAllExceptions</span><span class="params">(Exception ex, WebRequest request)</span> &#123;</span><br><span class="line">        <span class="comment">// 当出现异常时，我们输出的信息，这里被封装在了ExceptionResponse</span></span><br><span class="line">        <span class="type">ExceptionResponse</span> <span class="variable">exceptionResponse</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ExceptionResponse</span>(<span class="keyword">new</span> <span class="title class_">Date</span>(), ex.getMessage(), request.getDescription(<span class="literal">false</span>));</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ResponseEntity</span>(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">      * 当页面资源没有找到时，抛出的异常(404)</span></span><br><span class="line"><span class="comment">      *</span></span><br><span class="line"><span class="comment">      * <span class="doctag">@param</span> ex</span></span><br><span class="line"><span class="comment">      * <span class="doctag">@param</span> request</span></span><br><span class="line"><span class="comment">      * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">      */</span></span><br><span class="line">    <span class="meta">@ExceptionHandler(NotFoundException.class)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">final</span> ResponseEntity&lt;Object&gt; <span class="title function_">handleUserNotFoundExceptions</span><span class="params">(NotFoundException ex, WebRequest request)</span> &#123;</span><br><span class="line">        <span class="type">ExceptionResponse</span> <span class="variable">exceptionResponse</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ExceptionResponse</span>(<span class="keyword">new</span> <span class="title class_">Date</span>(), ex.getMessage(), request.getDescription(<span class="literal">false</span>));</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ResponseEntity</span>(exceptionResponse, HttpStatus.NOT_FOUND);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>启动 spring boot</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4d5896c2/image-20210106142601981.webp" alt="img"></p><p>这三个字段就是我们在 ExceptionResponse 自己定义的</p><p>本文 <a href="https://blog.imzjw.cn/posts/4d5896c2.html">Spring Boot 自定义通用异常 </a>就到这了</p></li></ol>]]></content>
    
    
    <summary type="html">如果一个项目都包含了各种各样的服务。每个服务都又以不同的方式返回异常信息，这样排查的时候就会比较麻烦。如果我们定义一个标准的异常处理体系。并在所有的服务中使用</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring Boot" scheme="https://blog.imzjw.cn/tags/Spring-Boot/"/>
    
  </entry>
  
  <entry>
    <title>抢先使用JetBrains的静态分析和代码质量管理工具</title>
    <link href="https://blog.imzjw.cn/posts/jetbrains-qodana/"/>
    <id>https://blog.imzjw.cn/posts/jetbrains-qodana/</id>
    <published>2021-01-05T03:20:05.000Z</published>
    <updated>2021-01-05T03:20:05.000Z</updated>
    
    <content type="html"><![CDATA[<p>今天的主人公是 Qodana</p><p>Qodana 是 JetBrains 团队工具系列中的新产品，它是用于代码质量监视的强大，灵活的解决方案。该产品的目的是识别并提出针对代码库中的错误，安全漏洞，重复项和缺陷的修补程序。将JetBrains的经验与代码开发相结合，并且与许多其他产品相交以增强和增强其功能。</p><div class="tip warning faa-horizontal animated faa-fast"><p>Qodana可以在任何CI工具上运行</p></div><h2 id="语言支持"><a href="#语言支持" class="headerlink" title="语言支持"></a>语言支持</h2><p>Qodana目前仅支持 <code>PHP</code>，<code>Java</code> 和 <code>Kotlin</code>，后面会支持 <code>JetBrains IDE</code> 家族下的语言和技术。敬请期待吧</p><h2 id="如何使用"><a href="#如何使用" class="headerlink" title="如何使用"></a>如何使用</h2><h3 id="Docker"><a href="#Docker" class="headerlink" title="Docker"></a>Docker</h3><p>首先，从 Docker Hub 拉取镜像</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull jetbrains/qodana</span><br></pre></td></tr></table></figure><p>运行以下命令，将 <code>&lt;source-directory&gt;</code> 替换为项目的根路径，然后打开打印在命令行输出中的 URL 以查看报告。</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run --<span class="built_in">rm</span> -it -v &lt;source-directory&gt;/:/data/project/ -p 8080:8080 jetbrains/qodana --show-report</span><br></pre></td></tr></table></figure><p>例如</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run --<span class="built_in">rm</span> -it -v /root/docker_springboot/:/data/project/ -p 8080:8080 jetbrains/qodana --show-report</span><br></pre></td></tr></table></figure><p>扫描过程可能有点久，我们稍等片刻</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/jetbrains-qodana/qodanaimage-20210105113959392.webp" alt="img"></p><p>扫描完成之后会在命令行输出 URL，然后我们在浏览器打开 URL</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/jetbrains-qodana/qodanaimage-20210105114443823.webp" alt="img"></p><p>大功告成！</p><p>既然刚刚说了 Qodana 可以在任何CI工具上运行</p><p>那我们就简单的在 GitHub Actions 中使用</p><h3 id="GitHub-Actions"><a href="#GitHub-Actions" class="headerlink" title="GitHub Actions"></a>GitHub Actions</h3><p><strong>前提</strong></p><p>准备一个要进行扫描的项目</p><p>准备一个 GitHub 仓库</p><ol><li><p>首先在你项目的根目录新建 <code>.github</code> 文件夹 然后 <kbd>C</kbd><kbd>D</kbd> 到 <code>.github</code> 新建 <code>workflows</code> 文件夹，最后在 <code>workflows</code> 文件夹新建 <code>qodana.yml</code> 文件</p><p>懒的话，可以在项目的根目录打开 Git Bash Here 执行如下命令</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> .github &amp;&amp; <span class="built_in">cd</span> .github &amp;&amp; <span class="built_in">mkdir</span> workflows &amp;&amp; <span class="built_in">cd</span> workflows &amp;&amp; <span class="built_in">touch</span> qodana.yml</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/jetbrains-qodana/qodanaimage-20210105121158850.webp" alt="img"></p></li><li><p>打开 <a href="https://github.com/JetBrains/qodana-action/blob/main/.github/workflows/example.yml">qodana.yml</a>，吧里面的内容复制到你的 <code>qodana.yml</code></p></li><li><p>push 到 GitHub 仓库</p></li><li><p>进入你的仓库点击 Actions</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/jetbrains-qodana/qodanaimage-20210105122430352.webp" alt="img"></p></li><li><p>点击步骤看图中序号</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/jetbrains-qodana/qodanaimage-20210105122624762.webp" alt="img"></p></li><li><p>就可以看到正在执行中了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/jetbrains-qodana/qodanaimage-20210105122732234.webp" alt="img"></p></li><li><p>执行成功</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/jetbrains-qodana/qodanaimage-20210105123106757.webp" alt="img"></p></li><li><p>下载 ZIP</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/jetbrains-qodana/qodanaimage-20210105123218846.webp" alt="img"></p></li></ol><p>大功告成！</p><p>非常简单</p><p>Qodana GitHub</p><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/JetBrains/Qodana"><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://gcard.imzjw.cn/api/pin/?username=JetBrains&repo=Qodana&theme=vue&show_owner=true"/></a>]]></content>
    
    
    <summary type="html">Qodana 是 JetBrains 团队工具系列中的新产品，它是用于代码质量监视的强大，灵活的解决方案。该产品的目的是识别并提出针对代码库中的错误，安全漏洞，重复项和缺陷的修补程序。将JetBrains的经验与代码开发相结合，并且与许多其他产品相交以增强和增强其功能。</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Qodana" scheme="https://blog.imzjw.cn/tags/Qodana/"/>
    
  </entry>
  
  <entry>
    <title>git clone从kb变成mb</title>
    <link href="https://blog.imzjw.cn/posts/5a2462ee/"/>
    <id>https://blog.imzjw.cn/posts/5a2462ee/</id>
    <published>2021-01-02T04:25:21.000Z</published>
    <updated>2021-03-25T03:20:33.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>虽然国内有码云，coding 等，但我个人还是喜欢 <code>github</code>，毕竟用户量摆在那，而且还是全球的大佬都在那开源贡献，我很喜欢这种精神，很棒，向他们致敬</p><p>但是，国内在 GitHub 克隆速度非常慢，龟速下载</p><p>如图，最慢 30 多 k，最快接近 200 k，然后就慢慢的又下降到几十 k….照这速度，不知道猴年马月能克隆完成</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/5a2462ee/image-20210102132142733.webp" alt="img" /><p>那么如何从几十 k 的速度变成 mb 呢？</p><h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><p>其实就是给 Git 设置代理</p><p>如果你克隆的是 HTTPS 协议，那么就输入如下命令</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git config --global http.proxy socks5://127.0.0.1:7890 <span class="comment"># 设置全局代理</span></span><br></pre></td></tr></table></figure><p>至于 <code>7890</code> 这个端口号，取决于你代理</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/5a2462ee/image-20201228141202222.webp" alt="img"></p><p>设置代理之后再来看下克隆的速度</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/5a2462ee/image-20210102140141497.webp" alt="img" /><p>哦麦嘎等，<code>7m</code> 了呢</p><p>但是有的人呢，不仅用 GitHub 还用国内的托管平台，那如果设置全局代理之后，在国内的托管平台上克隆的话难免会遇到点问题</p><p>如果你只想针对 GitHub 的话，如下命令</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git config --global http.https://github.com.proxy socks5://127.0.0.1:7890</span><br></pre></td></tr></table></figure><p>取消全局代理命令</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git config --global --<span class="built_in">unset</span> http.proxy</span><br></pre></td></tr></table></figure><p>当你设置如上的 HTTPS 协议的代理时，你会发现😮，你克隆像 <code>git@github.com:xxx/xxx.git</code> 这种 <code>SSH</code> 协议的话并没有走代理</p><p>这时我们先去 <code>user/.ssh/config</code> 看看有没有 config 文件，没有的话自己手动创建一个（<code>touch config</code>）</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/5a2462ee/image-20210102134652878.webp" alt="img" /><p>添加 <code>ProxyCommand connect -S 127.0.0.1:7890 %h %p</code> 即可</p><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 默认账户</span></span><br><span class="line"><span class="comment"># -S 是 SOCKS5 代理，想用 http / https 代理，把 S 改成 H 即可</span></span><br><span class="line"><span class="attr">ProxyCommand</span> <span class="string">connect -S 127.0.0.1:7890 %h %p</span></span><br><span class="line"><span class="attr">Host</span> <span class="string">github.com</span></span><br><span class="line"><span class="attr">HostName</span> <span class="string">github.com</span></span><br><span class="line"><span class="attr">User</span> <span class="string">git</span></span><br><span class="line"><span class="attr">IdentityFile</span> <span class="string">~/.ssh/id_rsa</span></span><br></pre></td></tr></table></figure><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/5a2462ee/image-20210102135927799.webp" alt="img" /><p>可以看到，接近 5 mb 了，如果没有代理，可以看我的另一篇 <a href="https://blog.imzjw.cn/posts/chrome-github-plugins/#GitHub-%E5%8A%A0%E9%80%9F">GitHub 加速 - Chrome 插件</a></p><h2 id="npm-配置代理"><a href="#npm-配置代理" class="headerlink" title="npm 配置代理"></a>npm 配置代理</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm config <span class="built_in">set</span> proxy http://127.0.0.1:7890</span><br></pre></td></tr></table></figure><p>取消代理</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm config delete proxy</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
        
        
    <summary type="html"></summary>
        
      
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="Git" scheme="https://blog.imzjw.cn/tags/Git/"/>
    
  </entry>
  
  <entry>
    <title>IDEA 一键部署 Spring Boot 项目到 Docker 容器</title>
    <link href="https://blog.imzjw.cn/posts/docker-deploy-springboot/"/>
    <id>https://blog.imzjw.cn/posts/docker-deploy-springboot/</id>
    <published>2020-12-31T03:45:14.000Z</published>
    <updated>2020-12-31T03:45:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>我知道的一些打包部署方式无非就是直接打成 jar 包然后扔进服务器（java -jar），又或者打成 war 包扔到 Tomcat</p><p>但是容器化部署方式应该是目前的主流方案吧</p><h2 id="Docker-安装"><a href="#Docker-安装" class="headerlink" title="Docker 安装"></a>Docker 安装</h2><ol><li><p>服务器（CentOS 7）没有服务器的话可以在本地装个 <a href="https://www.vmware.com/">VMware</a> 虚拟机，然后去 <a href="https://www.centos.org/download/">CentOS官网</a> 下个镜像安装</p></li><li><p>安装 Docker</p><ul><li><p>其实安装 Docker 也是非常非常的简单，网上也有很多教程</p><p>首先安装所需的软件包</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo yum install -y yum-utils \</span><br><span class="line">  device-mapper-persistent-data \</span><br><span class="line">  lvm2</span><br></pre></td></tr></table></figure><p>使用阿里云的镜像地址</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">yum-config-manager \</span><br><span class="line">    --add-repo \</span><br><span class="line">    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo</span><br></pre></td></tr></table></figure><p>安装 Docker Engine-Community</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install docker-ce docker-ce-cli containerd.io</span><br></pre></td></tr></table></figure><p>最后直接启动 Docker。</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">systemctl start docker</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看docker版本</span></span><br><span class="line">docker -v</span><br></pre></td></tr></table></figure></li></ul></li></ol><h3 id="配置-Docker"><a href="#配置-Docker" class="headerlink" title="配置 Docker"></a>配置 Docker</h3><p>Docker 安装成功之后，我们需要修改 Docker 配置，也就是开启允许远程访问 Docker 的功能</p><p>修改 <code>/usr/lib/systemd/system/docker.service</code> 文件</p><p>在 <code>ExecStart=/usr/bin/dockerd</code> 后面加上 <code>-H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock</code></p><p>如图</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231120816497.webp" alt="img" /><p>配置完成后，保存退出（先按 esc –&gt; :wq），然后重启 Docker</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 重启守护进程</span></span><br><span class="line">systemctl daemon-reload</span><br><span class="line"><span class="comment"># 重启docker</span></span><br><span class="line">service docker restart</span><br></pre></td></tr></table></figure><p>如何验证是否开启了呢？</p><p>在浏览器输入 <code>http://服务器 IP:2375/images/json</code></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231121217433.webp" alt="img" width="80%" height="400" /><p>验证成功的话，那么 Docker 的安装配置就算完成了，接下来转战到 <code>IDEA</code></p><h2 id="IDEA-配置"><a href="#IDEA-配置" class="headerlink" title="IDEA 配置"></a>IDEA 配置</h2><p>首先得装个插件，不过我 <code>IDEA 2018.3</code> 安装的时候就默认自带的，不过保险起见</p><p>还是得到 <code>File-&gt; Settings -&gt; Plugins -&gt; Marketplace</code> 查看一下是否安装 Docker 插件</p><p>如果 Installed 是灰色按钮的话，说明安装了，没有的话直接点 Installed 然后重启 IDEA</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231121858033.webp" alt="img" /><p>接着我们打开 <code>File -&gt; Settings -&gt; Build, Execution, Deployment -&gt; Docker</code></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231122421832.webp" alt="img" /><p>IDEA 配置就算完成了，接下来就是要准备个 Spring Boot 项目了</p><h2 id="项目配置"><a href="#项目配置" class="headerlink" title="项目配置"></a>项目配置</h2><p>在 <code>pom.xml</code> 加入 <code>spring-boot-starter-web</code> 依赖就好啦</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><p>然后创建个类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestDockerController</span> &#123;</span><br><span class="line"></span><br><span class="line">   <span class="meta">@RequestMapping(&quot;/test&quot;)</span></span><br><span class="line">   <span class="keyword">public</span> String <span class="title function_">testDocker</span><span class="params">()</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="string">&quot;test docker&quot;</span>;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="创建-Dockerfile"><a href="#创建-Dockerfile" class="headerlink" title="创建 Dockerfile"></a>创建 Dockerfile</h3><p>在项目的根目录下 new 一个 file 取名为 <code>Dockerfile </code></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231123424959.webp" alt="img" /><p>并加入以下内容</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> hub.c.<span class="number">163</span>.com/library/java:latest</span><br><span class="line"><span class="keyword">MAINTAINER</span> david <span class="string">&quot;xxx@xxx.xxx&quot;</span></span><br><span class="line"><span class="keyword">VOLUME</span><span class="language-bash"> /tmp</span></span><br><span class="line"><span class="keyword">ADD</span><span class="language-bash"> target/docker_springboot-0.0.1-SNAPSHOT.jar app.jar</span></span><br><span class="line"><span class="keyword">ENTRYPOINT</span><span class="language-bash"> [<span class="string">&quot;java&quot;</span>,<span class="string">&quot;-jar&quot;</span>,<span class="string">&quot;/app.jar&quot;</span>]</span></span><br></pre></td></tr></table></figure><h3 id="配置-Maven-插件"><a href="#配置-Maven-插件" class="headerlink" title="配置 Maven 插件"></a>配置 Maven 插件</h3><p>在 <code>pom.xml</code>，添加如下插件</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.spotify<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>docker-maven-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.2.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">executions</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">id</span>&gt;</span>build-image<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">phase</span>&gt;</span>package<span class="tag">&lt;/<span class="name">phase</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">goals</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">goal</span>&gt;</span>build<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">executions</span>&gt;</span></span><br><span class="line"></span><br><span class="line">            <span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">dockerHost</span>&gt;</span>http://服务器IP:2375<span class="tag">&lt;/<span class="name">dockerHost</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">imageName</span>&gt;</span>garvey/$&#123;project.artifactId&#125;<span class="tag">&lt;/<span class="name">imageName</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">imageTags</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">imageTag</span>&gt;</span>$&#123;project.version&#125;<span class="tag">&lt;/<span class="name">imageTag</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">imageTags</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">forceTags</span>&gt;</span>true<span class="tag">&lt;/<span class="name">forceTags</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">dockerDirectory</span>&gt;</span>$&#123;project.basedir&#125;<span class="tag">&lt;/<span class="name">dockerDirectory</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">resources</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">resource</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">targetPath</span>&gt;</span>/<span class="tag">&lt;/<span class="name">targetPath</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">directory</span>&gt;</span>$&#123;project.build.directory&#125;<span class="tag">&lt;/<span class="name">directory</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">include</span>&gt;</span>$&#123;project.build.finalName&#125;.jar<span class="tag">&lt;/<span class="name">include</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">resource</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">plugins</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br></pre></td></tr></table></figure><p>OK 啦，接下来直接打包</p><h3 id="打包"><a href="#打包" class="headerlink" title="打包"></a>打包</h3><p>点击 <code>package</code> 即可</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231123837906.webp" alt="img" /><p>第一次打包，需要下载基础镜像，可能会慢一点，耐心等待就好了</p><p>然后就会看到控制台的打包 log</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231124725387.webp" alt="img" /><p>打包成功之后我们就可以在 Docker 容器中看到我们刚刚打包的镜像了</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker images</span><br></pre></td></tr></table></figure><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231124044347.webp" alt="img" /><h3 id="启动方式"><a href="#启动方式" class="headerlink" title="启动方式"></a>启动方式</h3><ol><li><p>（第一种）像创建普通容器一样创建这个镜像的容器，输入如下命令</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -d --name garvey -p 8080:8080 garvey/docker_springboot:0.0.1-SNAPSHOT</span><br></pre></td></tr></table></figure><p>启动成功之后，我们就可以访问了。</p><p><code>http://服务器 IP:8080/test</code></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231124844886.webp" alt="img" /></li><li><p>（第二种）在 IDEA 中运行（推荐）</p><p>在 IDEA 中连接到了 Docker 之后你就会发现 <code>Tool Buttons</code> 多了个 Docker 的工具栏</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231125346719.webp" alt="img" /><p>接着点击左边那个绿色的启动按钮</p><p>启动成功后我们就可以看到目前 Docker 中的所有容器和镜像了</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231125509274.webp" alt="img" /><p>此时，我们选中刚刚打包的镜像，右键 <code>Create container -&gt; Create...</code></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231125558139.webp" alt="img" /><p>配置容器名称和端口映射关系即可</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231125810176.webp" alt="img" /><div class="note danger flat"><p>注意：如果你刚刚在 Docker 启动过了的话，你要先停止它，不然端口会被占用的</p></div><p>运行 log 如下</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/docker-deploy-springboot/springbootimage-20201231130031046.webp" alt="img" /><p>运行成功之后还是一样在浏览器输入 <code>http://服务器 IP:8080/test</code> 访问</p><p>这样我们的 Spring Boot 项目就发布到 Docker 容器中了</p></li></ol>]]></content>
    
    
    <summary type="html">我知道的一些打包部署方式无非就是直接打成 jar 包然后扔进服务器（java -jar），又或者打成 war 包扔到 Tomcat，但是容器化部署方式应该是目前的主流方案吧</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring Boot" scheme="https://blog.imzjw.cn/tags/Spring-Boot/"/>
    
  </entry>
  
  <entry>
    <title>无需服务器和域名快速搭建部署Vue仿网易云</title>
    <link href="https://blog.imzjw.cn/posts/vue-netease-music/"/>
    <id>https://blog.imzjw.cn/posts/vue-netease-music/</id>
    <published>2020-12-28T06:40:57.000Z</published>
    <updated>2021-03-20T10:30:22.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>今天偶然间在 GitHub 上发现了一个 Star 1.4k 的 <a href="https://github.com/sl1673495/vue-netease-music">基于 Vue2、Vue-CLI3 的高仿网易云 mac 客户端播放器</a> 的项目，深深的被 ✔引，没有把持住，因此无聊就玩了玩，随便也记录了一下，便有了此篇文章，大概一首歌的时间就搭建好了。</p><a class="btn-beautify pink" href="https://vuemusic.cf/"   title="演示地址"><i class="far fa-hand-point-right"></i><span>演示地址</span></a><h2 id="前期准备"><a href="#前期准备" class="headerlink" title="前期准备"></a>前期准备</h2><ol><li>GitHub 账号，没有的自行 <a href="https://www.google.com/">Google</a> 如何注册</li><li>安装 node、Git 环境，下载地址：<a href="https://npm.taobao.org/mirrors/node/">node 阿里云镜像地址</a> | <a href="https://npm.taobao.org/mirrors/git-for-windows/">Git 阿里云镜像地址</a></li><li>Vercel 账号，没有的可以去<a href="https://vercel.com/signup">注册</a></li></ol><h2 id="正式开始"><a href="#正式开始" class="headerlink" title="正式开始"></a>正式开始</h2><p>首先把项目 <code>clone</code> 下来到本地</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/sl1673495/vue-netease-music.git</span><br></pre></td></tr></table></figure><p>如果 <code>clone</code> 较慢的话可以用这个地址</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com.cnpmjs.org/sl1673495/vue-netease-music.git</span><br></pre></td></tr></table></figure><p><code>clone</code> 到本地之后先执行 <code>npm i</code> 安装依赖，你就会发现项目里多了个 <code>node_modules</code>，这里面其实就是装了这个项目所依赖的所有依赖包</p><p><code>npm</code> 慢的话可以设置代理</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm config <span class="built_in">set</span> https-proxy <span class="string">&quot;http://127.0.0.1:7890&quot;</span> <span class="comment"># 端口是根据你的代理是啥端口就是啥端口</span></span><br></pre></td></tr></table></figure><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228141202222.webp" alt="img"><p>取消代理命令</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm config delete https-proxy</span><br></pre></td></tr></table></figure><p>很不推荐 <code>cnpm</code>，实在没办法那就用 <code>cnpm</code> 吧！</p><p>当安装完依赖之后，我们输入 <code>npm run dev</code>，可以在本地运行调式，默认端口是 <code>8888</code>，当然你也可以在 <code>vue.config.js</code> 里面更改</p><p>本地调式完无误之后我们直接输入 <code>npm run build</code> 进行打包，就会生成个打包后的目录：music</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228142107290.webp" alt="img"/><h2 id="部署"><a href="#部署" class="headerlink" title="部署"></a>部署</h2><p>部署方式本文就讲两种，Vercel 和 Gitee （码云）更推荐 Vercel，当然还有 <a href="https://www.netlify.com/">Netlify</a>，会的话就自己整哦！</p><p>这俩的区别前者可以自定义域名，而码云不能，且还得手动更新</p><div class="tabs" id="test"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="test-1">Vercel 方式</button><button type="button" class="tab " data-href="test-2">Gitee 方式</button></ul><div class="tab-contents"><div class="tab-item-content active" id="test-1"><p>登录 <a href="https://github.com/login">GitHub</a>，<a href="https://github.com/new">创建仓库</a>，仓库名称随意</p><p>把刚刚打包后的 music 文件夹下的内容 push 到 GitHub 上</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228145035546.webp" alt="images"></p><p>接着 <a class="btn-beautify pink" href="https://vercel.com/"   title="点击"><i class="far fa-hand-point-right"></i><span>点击</span></a> 打开 Vercel 官网</p><p>右上角点击 <a href="https://vercel.com/signup">Sign Up</a>，使用 GitHub 注册</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228144101989.webp" alt="img"/><p>点击 Authorize Vercel（授权给 Vercel）</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228144223350.webp" alt="img"/><p>接着输入手机号码进行验证（有人说不需要）唔~我也不清楚，反正我注册的时候要输入…</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228144428702.webp" alt="img"/><p>验证成功之后我们点击 Continue</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228144838966.webp" alt="img"/><p>输入你 GitHub 仓库地址（也就是你刚刚打包 push 到 GitHub 的仓库地址）</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228144858933.webp" alt="img"/><p>然后就继续 Continue，最后 Deploy</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228145822068.webp" alt="img"/><p>最后没了，已经部署成功啦！</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228145943215.webp" alt="img"/><p>部署成功后 Vercel 会默认自带个二级域名，点击即可访问，我们也可以自定义 Vercel 提供的二级域名</p><p>点击 Settings –&gt; Domains</p><p>格式为：<code>xxx.vercel.app</code>，xxx 表示你自定义的，点击右侧 <code>Add</code>，如果没有人使用的话，会自动验证成功。</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228150428825.webp" alt="img"/><p>如果你想绑定自己域名的话，那你就直接输入自己的域名，点击 Add 即可，下方会提示 <code>Invalid Config...</code></p><p>然后在域名购买方控制台进行域名解析。解析完成后即可通过自己的域名访问。</p><p>大功告成！！</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228150617547.webp" alt="img"/></div><div class="tab-item-content" id="test-2"><p>注册登录不阐述了，创建与 Gitee 用户名相同的仓库，不然会出现 404 问题，除非你改源码。</p><p>把刚刚打包后的 music 文件夹下的内容 push 到 Gitee 上</p><p>然后点击服务 –&gt; <code>Gitee Pages</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/20210320192044.webp" alt="Gitee Pages"></p><hr><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228151023145.webp" alt="images"/><hr><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/vue-netease-music/image-20201228151052111.webp" alt="zjwo.gitee.io"/></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><p>如有问题，请在下方评论！</p>]]></content>
    
    
    <summary type="html">今天偶然间在 GitHub 上发现了一个 Star 1.4k 的基于 Vue2、Vue-CLI3 的高仿网易云 mac 客户端播放器的项目，深深的被 ✔引，没有把持住，因此无聊就玩了玩，随便也记录了一下</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Vue" scheme="https://blog.imzjw.cn/tags/Vue/"/>
    
  </entry>
  
  <entry>
    <title>总结壁纸网站含4K/8K</title>
    <link href="https://blog.imzjw.cn/posts/wallpaper-site/"/>
    <id>https://blog.imzjw.cn/posts/wallpaper-site/</id>
    <published>2020-12-24T07:09:57.000Z</published>
    <updated>2020-12-24T07:09:57.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="极简壁纸"><a href="#极简壁纸" class="headerlink" title="极简壁纸"></a>极简壁纸</h2><p>官网：<a href="https://bz.zzzmh.cn/">https://bz.zzzmh.cn</a><br>分类：精选、人物、二次元、筛选、喜欢</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224151401467.webp" alt="img"></p><h2 id="必应壁纸"><a href="#必应壁纸" class="headerlink" title="必应壁纸"></a>必应壁纸</h2><p>官网：<a href="https://bing.ioliu.cn/">https://bing.ioliu.cn</a><br>分类：首页、下载榜</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224151447347.webp" alt="img"></p><h2 id="千叶网"><a href="#千叶网" class="headerlink" title="千叶网"></a>千叶网</h2><p>官网：<a href="http://qianye88.com/">http://qianye88.com</a><br>分类：4k 动漫、4k 美女、4k 风景、4k 游戏 等太多了，自己到官网看吧</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224151708369.webp" alt="img"></p><h2 id="pexels"><a href="#pexels" class="headerlink" title="pexels"></a>pexels</h2><p>官网：<a href="https://www.pexels.com/">https://www.pexels.com</a><br>分类：摄影为主<br>据说是全球顶尖高清摄影图片分享网站，免费授权商用</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224151754551.webp" alt="img"></p><h2 id="unsplash"><a href="#unsplash" class="headerlink" title="unsplash"></a>unsplash</h2><p>官网：<a href="https://unsplash.com/">https://unsplash.com</a><br>分类：各种都有<br>纯粹、简单、优雅，高质量无版权图片分享圣地</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224151924610.webp" alt="img"></p><h2 id="pixabay"><a href="#pixabay" class="headerlink" title="pixabay"></a>pixabay</h2><p>官网：<a href="https://pixabay.com/">https://pixabay.com</a><br>分类：摄影为主<br>提供海量免费高清图片、插画、矢量素材，图片超美，支持中文好评！</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224152022588.webp" alt="img"></p><h2 id="Wallhaven"><a href="#Wallhaven" class="headerlink" title="Wallhaven"></a>Wallhaven</h2><p>官网：<a href="https://wallhaven.cc/">https://wallhaven.cc/</a></p><p>分类：赛博朋克、动漫、4K、英雄联盟、极简主义等</p><p>图片质量超高，无论是二次元还是摄影题材，可以说应有尽有，排版精美</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224152137904.webp" alt="img"></p><h2 id="Wunderstock"><a href="#Wunderstock" class="headerlink" title="Wunderstock"></a>Wunderstock</h2><p>官网：<a href="https://wunderstock.com/">https://wunderstock.com/</a></p><p>分类：性质、餐饮、动物、时尚等</p><p>排版精美，图片分辨率很大，图库超大</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224152337588.webp" alt="img"></p><h2 id="Wallls"><a href="#Wallls" class="headerlink" title="Wallls"></a>Wallls</h2><p>官网：<a href="http://wallls.com/">http://wallls.com/</a></p><p>分类：太空艺术、房间、鸟类、汽车、鸣人等</p><p>图片以分类形式呈现，排版无可挑剔，质量也很高。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224152453773.webp" alt="img"></p><h2 id="Wallpaper"><a href="#Wallpaper" class="headerlink" title="Wallpaper"></a>Wallpaper</h2><p>网站：<a href="https://wall.alphacoders.com/?lang=Chinese">Wallpaper</a></p><p>巨无霸网站，用户众多，近百万优质 4k 图源，缩略图直接显示分辨率。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224152632768.webp" alt="img"></p><h2 id="Wallroom"><a href="#Wallroom" class="headerlink" title="Wallroom"></a>Wallroom</h2><p>网站：<a href="https://wallroom.io/">https://wallroom.io/</a></p><p>分类：最新、1920、2560、2880、4K、5K、8K 等</p><p>主打 4K、8K 等超清图片，质量极高，排版也很舒适。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224152807385.webp" alt="img"></p><h2 id="彼岸图网"><a href="#彼岸图网" class="headerlink" title="彼岸图网"></a>彼岸图网</h2><p>网站：<a href="http://pic.netbian.com/">http://pic.netbian.com/</a></p><p>分类：4k 风景、4K 动漫、4K 风景、4K 美食、4K 背景等….</p><p>主打 4k+ 图源，素材较丰富，亮点是中文网站。大量下载需要会员，永久 30 RMB 左右。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224152830958.webp" alt="img"></p><h2 id="Wallhere"><a href="#Wallhere" class="headerlink" title="Wallhere"></a>Wallhere</h2><p>官网：<a href="https://wallhere.com/">https://wallhere.com/</a></p><p>分类：汽车、森林、云彩等</p><p>排版超赞，图片也很棒，分辨率很高，挑选电脑壁纸完全没有问题。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224153235667.webp" alt="img"></p><h2 id="Piqsels"><a href="#Piqsels" class="headerlink" title="Piqsels"></a>Piqsels</h2><p>官网：<a href="https://www.piqsels.com/zh">https://www.piqsels.com/zh</a></p><p>首页很有格调，图片质量也很好，可以免费下载原图，免版税图片，可商用.</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224153752547.webp" alt="img"></p><h2 id="Alphacoder"><a href="#Alphacoder" class="headerlink" title="Alphacoder"></a>Alphacoder</h2><p>官网：<a href="https://alphacoders.com/">https://alphacoders.com/</a></p><p>图库超大，可自行搜索 4K</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224153922157.webp" alt="img"></p><h2 id="Goodfon"><a href="#Goodfon" class="headerlink" title="Goodfon"></a>Goodfon</h2><p>官网：<a href="https://www.goodfon.com/">https://www.goodfon.com/</a></p><p>国外分享壁纸的网站，缩略图能直接显示是 2K、3K、4K 等，质量很高。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224154009696.webp" alt="img"></p><h2 id="WallpaperCave"><a href="#WallpaperCave" class="headerlink" title="WallpaperCave"></a>WallpaperCave</h2><p>官网：<a href="https://wallpapercave.com/">https://wallpapercave.com/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224154112926.webp" alt="img"></p><h2 id="WallpapersCraft"><a href="#WallpapersCraft" class="headerlink" title="WallpapersCraft"></a>WallpapersCraft</h2><p>官网：<a href="https://wallpaperscraft.com/">https://wallpaperscraft.com/</a></p><p>分类：3D、艺术、动漫、黑暗、极简主义、假期等…</p><p>分类比较齐全，排版、找图体验不是很好</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224154222334.webp" alt="img"></p><h2 id="Wallpaperswide"><a href="#Wallpaperswide" class="headerlink" title="Wallpaperswide"></a>Wallpaperswide</h2><p>官网：<a href="http://wallpaperswide.com/">http://wallpaperswide.com/</a></p><p>分类：动物、建筑、航空、体育等</p><p>排版一般般，但是质量很棒</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224154449577.webp" alt="img"></p><h2 id="Visualhunt"><a href="#Visualhunt" class="headerlink" title="Visualhunt"></a>Visualhunt</h2><p>官网：<a href="https://visualhunt.com/">https://visualhunt.com/</a></p><p>几亿量级的专业图片库，界面精美，不过找图片要往下翻一翻。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224154526951.webp" alt="img"></p><h2 id="Foodiesfeed"><a href="#Foodiesfeed" class="headerlink" title="Foodiesfeed"></a>Foodiesfeed</h2><p>官网：<a href="https://www.foodiesfeed.com/">https://www.foodiesfeed.com/</a></p><p>专注食品拍照，质量极高，注意不要在睡觉的时候看…</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224154614969.webp" alt="img"></p><h2 id="Psiupuxa"><a href="#Psiupuxa" class="headerlink" title="Psiupuxa"></a>Psiupuxa</h2><p>官网：<a href="https://psiupuxa.com/">https://psiupuxa.com/</a></p><p>浩瀚宇宙星空，包括星球表面，排版充满科技感，质量很高。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224154751433.webp" alt="img"></p><h2 id="10WALLPAPER"><a href="#10WALLPAPER" class="headerlink" title="10WALLPAPER"></a>10WALLPAPER</h2><p>官网：<a href="https://10wallpaper.com/">https://10wallpaper.com/</a></p><p>分类：植物、动物、小姐姐、游戏、设计</p><p>主打4K的壁纸网站，质量超高，10w左右的精美壁纸。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224154820884.webp" alt="img"></p><h2 id="H128壁纸"><a href="#H128壁纸" class="headerlink" title="H128壁纸"></a>H128壁纸</h2><p>官网：<a href="https://www.h128.com/">https://www.h128.com/</a></p><p>分类：动漫、游戏、明星、美食等</p><p>主打 4K、6K 甚至 8K 图片，中文免费网站</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224155021686.webp" alt="img"></p><h2 id="National-Geographic"><a href="#National-Geographic" class="headerlink" title="National Geographic"></a>National Geographic</h2><p>官网：<a href="https://www.nationalgeographic.com/">https://www.nationalgeographic.com/</a></p><p>国家地理，象征顶级摄影的存在，其分量与质量不必多说，不过国内加载略慢。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224155107210.webp" alt="img"></p><h2 id="故宫博物院"><a href="#故宫博物院" class="headerlink" title="故宫博物院"></a>故宫博物院</h2><p>官网：<a href="https://www.dpm.org.cn/lights/royal.html">https://www.dpm.org.cn/lights/royal.html</a></p><p>作为全世界的文化遗产，故宫拍下的图片质量很高，不过数量只有 1k 左右。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224155215152.webp" alt="img"></p><h2 id="Wallpapermaiden"><a href="#Wallpapermaiden" class="headerlink" title="Wallpapermaiden"></a>Wallpapermaiden</h2><p>官网：<a href="https://www.wallpapermaiden.com/">https://www.wallpapermaiden.com/</a></p><p>以二次元为主，分类齐全，质量较高。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224155233721.webp" alt="img"></p><h2 id="Cgwallpapers"><a href="#Cgwallpapers" class="headerlink" title="Cgwallpapers"></a>Cgwallpapers</h2><p>官网：<a href="https://www.cgwallpapers.com/">https://www.cgwallpapers.com/</a></p><p>CG 图片集合网站</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224155346141.webp" alt="img"></p><h2 id="Streetwill"><a href="#Streetwill" class="headerlink" title="Streetwill"></a>Streetwill</h2><p>官网：<a href="http://streetwill.co/">http://streetwill.co/</a></p><p>黑白风格街拍，质量较硬。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224155856512.webp" alt="img"></p><h2 id="Pixivic"><a href="#Pixivic" class="headerlink" title="Pixivic"></a>Pixivic</h2><p>官网：<a href="https://pixivic.com/?VNK=19e8f5b8">Pixivic</a></p><p>P站第三方网站，国内用户的福音，不多解释，看到就是赚到。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224155944505.webp" alt="img"></p><h2 id="图虫网"><a href="#图虫网" class="headerlink" title="图虫网"></a>图虫网</h2><p>官网：<a href="http://tuchong.com/">http://tuchong.com/</a></p><p>几亿量级的图片，以及较多的用户评论</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224160020839.webp" alt="img"></p><h2 id="堆糖"><a href="#堆糖" class="headerlink" title="堆糖"></a>堆糖</h2><p>官网：<a href="https://www.duitang.com/">https://www.duitang.com/</a></p><p>用户较多，以朋友圈形式分享图片，图片题材丰富</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224160146630.webp" alt="img"></p><h2 id="画师通"><a href="#画师通" class="headerlink" title="画师通"></a>画师通</h2><p>官网：<a href="https://www.huashi6.com/">https://www.huashi6.com/</a></p><p>P站国人画师们分享图片的网站，毋庸置疑很好看</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224160229663.webp" alt="img"></p><h2 id="花瓣"><a href="#花瓣" class="headerlink" title="花瓣"></a>花瓣</h2><p>官网：<a href="https://huaban.com/">https://huaban.com/</a></p><p>国内设计师采集图片的网站</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/wallpaper-site/image-20201224160311498.webp" alt="img"></p><p><strong>待续!!!</strong></p>]]></content>
    
    
    <summary type="html">极简壁纸-分类：精选、人物、二次元、筛选、喜欢,必应壁纸-分类：首页、下载榜,千叶网-4k 动漫、4k 美女、4k 风景、4k 游戏等</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="壁纸" scheme="https://blog.imzjw.cn/tags/%E5%A3%81%E7%BA%B8/"/>
    
  </entry>
  
  <entry>
    <title>Nginx 反向代理与负载均衡</title>
    <link href="https://blog.imzjw.cn/posts/nginx-proxy/"/>
    <id>https://blog.imzjw.cn/posts/nginx-proxy/</id>
    <published>2020-12-24T06:30:16.000Z</published>
    <updated>2020-12-24T06:30:16.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="代理"><a href="#代理" class="headerlink" title="代理"></a>代理</h2><p>要想弄明白反向代理，首先要知道啥是正向代理，要搞懂正向代理那就得知道啥是代理。</p><p>代理其实就是一个<code>中介</code>，在不同事物或同一事物内部起到之间联系作用的环节。比如买票黄牛，房屋中介等等。</p><p>在互联网中代理更多指的是<code>代理服务器</code></p><p>代理服务器位于客户端和服务器之间，它充当两者之间的中介。这种代理在生活中是比较常见的，比如我们常说的搭个梯子上网，用到的就是代理技术。</p><h2 id="正向代理"><a href="#正向代理" class="headerlink" title="正向代理"></a>正向代理</h2><p>是一个位于客户端和目标服务器之间的服务器(代理服务器)，为了从目标服务器取得内容，客户端向代理服务器发送一个请求并指定目标，然后代理服务器向目标服务器转交请求并将获得的内容返回给客户端。</p><p>比如国内访问谷歌，直接访问是不行的，我们可以通过一个能够访问谷歌的正向代理服务器，请求发到代理服务器，由代理去谷歌获取数据并返回，这样就变相的实现了访问谷歌的需求。</p><p>一句话总结正向代理 就是<code>代理服务器代理了客户端</code>，去和目标服务器进行交互。</p><h3 id="好处"><a href="#好处" class="headerlink" title="好处"></a>好处</h3><ul><li>突破 IP 访问限制</li><li>加速访问资源</li><li>隐藏客户端真实 <code>IP</code></li><li>客户端访问授权</li></ul><h2 id="反向代理"><a href="#反向代理" class="headerlink" title="反向代理"></a>反向代理</h2><p>与正向代理正好相反，反向代理中的代理服务器，代理的是服务器那端。代理服务器接收客户端请求，然后将请求转发给内部网络上的服务器，并将从服务器上得到的结果返回给客户端，此时代理服务器对外表现为一个反向代理服务器的角色。</p><p>反向代理服务器位于用户与目标服务器之间，但是对于用户而言，反向代理服务器就相当于目标服务器，即用户直接访问反向代理服务器就可以获得目标服务器的资源。同时，用户不需要知道目标服务器的地址</p><p>一句话总结反向代理 就是<code>代理服务器代理了目标服务器</code>，去和客户端进行交互。</p><h3 id="好处-1"><a href="#好处-1" class="headerlink" title="好处"></a>好处</h3><ul><li>隐藏服务器真实 <code>IP</code></li><li>负载均衡</li><li>加速访问资源</li><li>提供安全保障</li></ul><h2 id="负载均衡"><a href="#负载均衡" class="headerlink" title="负载均衡"></a>负载均衡</h2><p>实际生产环境中，反向代理服务器代理的目标服务器可能不止一个。比如开发好的某个应用部署在一台 <code>Tomcat</code> 服务器上，而 Tomcat 的并发上限不优化情况下，默认只有两百左右，这时候为了解决高并发的问题，就只能选择更换服务器或者搭建多台服务器通过反向代理与负载均衡的技术解决并发问题。</p><p>负载均衡是由多台服务器以对称的方式组成一个服务器集群，每台服务器都具有等价的地位，都可以单独对外提供服务而无须其他服务器的辅助。经过某种负载分管技术，将外部发送来的中央请求均匀分配到对称结构中的某一台服务器上。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>正向代理，就是<code>代理服务器代理了客户端</code>，去和目标服务器进行交互。现实生活中的场景：黄牛买票。</p><p>反向代理，就是<code>代理服务器代理了目标服务器</code>，去和客户端进行交互。现实生活中的场景：房屋中介。</p><p>如果还不明白，这里引用 <a href="https://foofish.net/proxy-and-reverse-proxy.html">军哥</a> 的两段话</p><h3 id="正向代理-1"><a href="#正向代理-1" class="headerlink" title="正向代理"></a>正向代理</h3><p>A 同学在大众创业、万众创新的大时代背景下开启他的创业之路，目前他遇到的最大的一个问题就是启动资金，于是他决定去找马云爸爸借钱，可想而知，最后碰一鼻子灰回来了，情急之下，他想到一个办法，找关系开后门，经过一番消息打探，原来 A 同学的大学老师王老师是马云的同学，于是 A 同学找到王老师，托王老师帮忙去马云那借 500 万过来，当然最后事成了。不过马云并不知道这钱是 A 同学借的，马云是借给王老师的，最后由王老师转交给 A 同学。这里的王老师在这个过程中扮演了一个非常关键的角色，就是<code>代理</code>，也可以说是正向代理，王老师代替 A 同学办这件事，这个过程中，真正借钱的人是谁，马云是不知道的，这点非常关键。</p><p>我们常说的代理也就是只正向代理，正向代理的过程，它隐藏了真实的请求客户端，服务端不知道真实的客户端是谁，客户端请求的服务都被代理服务器代替来请求，某些科学上网工具扮演的就是典型的正向代理角色。用浏览器访问 <code>http://www.google.com</code> 时，被残忍的 <code>block</code>，于是你可以在国外搭建一台代理服务器，让代理帮我去请求 <code>google.com</code>，代理把请求返回的相应结构再返回给我。</p><h3 id="反向代理-1"><a href="#反向代理-1" class="headerlink" title="反向代理"></a>反向代理</h3><p>大家都有过这样的经历，拨打 10086 客服电话，可能一个地区的 10086 客服有几个或者几十个，你永远都不需要关心在电话那头的是哪一个，叫什么，男的，还是女的，漂亮的还是帅气的，你都不关心，你关心的是你的问题能不能得到专业的解答，你只需要拨通了 10086 的总机号码，电话那头总会有人会回答你，只是有时慢有时快而已。那么这里的 10086 总机号码就是我们说的<code>反向代理</code>。客户不知道真正提供服务人的是谁。</p><p>反向代理隐藏了真实的服务端，当我们请求 <code>www.baidu.com</code> 的时候，就像拨打 10086 一样，背后可能有成千上万台服务器为我们服务，但具体是哪一台，你不知道，也不需要知道，你只需要知道反向代理服务器是谁就好了，<code>www.baidu.com</code> 就是我们的反向代理服务器，反向代理服务器会帮我们把请求转发到真实的服务器那里去。Nginx 就是性能非常好的反向代理服务器，用来做负载均衡。</p><p>参考：<a href="https://www.nginx.cn/doc/">https://www.nginx.cn/doc/</a></p>]]></content>
    
    
    <summary type="html">代理其实就是一个中介，在不同事物或同一事物内部起到之间联系作用的环节。比如买票黄牛，房屋中介等等。在互联网中代理更多指的是代理服务器</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Nginx" scheme="https://blog.imzjw.cn/tags/Nginx/"/>
    
  </entry>
  
  <entry>
    <title>被SpringBoot和IDEA支持的Lombok到底有何神奇之处</title>
    <link href="https://blog.imzjw.cn/posts/use-lombok/"/>
    <id>https://blog.imzjw.cn/posts/use-lombok/</id>
    <published>2020-12-23T11:51:10.000Z</published>
    <updated>2020-12-23T11:51:10.000Z</updated>
    
    <content type="html"><![CDATA[<p>最近 IDEA 2020 最后一个版本发布了，<code>听说</code>已经内置了 Lombok 插件，SpringBoot 2.1.x 之后的版本也在 Starter 中内置了 Lombok 依赖</p><h2 id="Lombok简介"><a href="#Lombok简介" class="headerlink" title="Lombok简介"></a>Lombok简介</h2><p>Lombok 是一款 <code>Java</code> 代码功能增强库，在 <a href="https://github.com/rzwitserloot/lombok">Github</a> 上已有 9.9 k Star。它会自动集成到你的编辑器和构建工具中，从而使你的 Java 代码更加生动有趣。通过 Lombok 的注解，你可以不用再写 getter、setter、equals 等方法，Lombok 将在编译时为你自动生成。</p><h2 id="Lombok安装"><a href="#Lombok安装" class="headerlink" title="Lombok安装"></a>Lombok安装</h2><p>首先我们需要在 <a href="https://www.jetbrains.com/zh-cn/idea/download/">IDEA</a> 中安装好 Lombok 插件，如果你使用的是最新版 IDEA <code>2020.3</code>，则 Lombok 插件已经内置，无需安装。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/use-lombok/image-20201223200032678.webp" alt="img"></p><p>之后在项目的  <code>pom.xml</code>  文件中添加 Lombok 依赖就好啦</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/use-lombok/image-20201223200948584.webp" alt="img"></p><p>SpringBoot 2.1.x 版本后无需指定 Lombok 版本，因为 SpringBoot 在  <code>spring-boot-dependencies</code>  中已经内置了 Lombok</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/use-lombok/image-20201223190118587.webp" alt="img"></p><h2 id="Lombok使用"><a href="#Lombok使用" class="headerlink" title="Lombok使用"></a>Lombok使用</h2><p>Lombok 中有很多注解，这些注解使得我们可以更加方便的编写 Java 代码，下面介绍下这些注解的使用。</p><h3 id="val"><a href="#val" class="headerlink" title="val"></a>val</h3><p>使用 <code>val</code> 注解可以取代任意类型作为局部变量，这样我们就不用写复杂的 <code>ArrayList</code> 和 <code>Map.Entry</code> 类型了，具体例子如下。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> https://blog.imzjw.cn</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2020/12/23 20:03</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LombokDemo</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        result();</span><br><span class="line">        result2();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">result</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// val代替 ArrayList&lt;String&gt; 和 String 类型</span></span><br><span class="line">        <span class="type">val</span> <span class="variable">list</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;String&gt;();</span><br><span class="line">        list.add(<span class="string">&quot;GARVEY ZHONG&quot;</span>);</span><br><span class="line">        <span class="type">val</span> <span class="variable">res</span> <span class="operator">=</span> list.get(<span class="number">0</span>);</span><br><span class="line">        <span class="comment">// toLowerCase：转小写</span></span><br><span class="line">        System.out.println(res.toLowerCase());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">result2</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// val 代替 Map.Entry&lt;Integer,String&gt; 类型</span></span><br><span class="line">        <span class="type">val</span> <span class="variable">map</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;Integer, String&gt;();</span><br><span class="line">        map.put(<span class="number">0</span>, <span class="string">&quot;blog.imzjw.cn&quot;</span>);</span><br><span class="line">        System.out.println(map.get(<span class="number">0</span>));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 打印结果</span></span><br><span class="line">===========================================================</span><br><span class="line"><span class="string">&quot;C:\Program Files\Java\jdk1.8.0_162\bin\java.exe&quot;</span>...</span><br><span class="line">garvey zhong</span><br><span class="line">blog.imzjw.cn</span><br><span class="line"></span><br><span class="line">Process finished with exit code <span class="number">0</span></span><br><span class="line">===========================================================</span><br></pre></td></tr></table></figure><p>当我们使用了 <code>val</code> 注解后，Lombok 会从局部变量的初始化表达式推断出具体类型，编译后会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LombokDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">LombokDemo</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">result</span><span class="params">()</span> &#123;</span><br><span class="line">        ArrayList&lt;String&gt; list = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">        list.add(<span class="string">&quot;GARVEY ZHONG&quot;</span>);</span><br><span class="line">        <span class="type">String</span> <span class="variable">res</span> <span class="operator">=</span> list.get(<span class="number">0</span>);</span><br><span class="line">        System.out.println(res.toLowerCase());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">result2</span><span class="params">()</span> &#123;</span><br><span class="line">        HashMap&lt;Integer, String&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line">        map.put(<span class="number">0</span>, <span class="string">&quot;blog.imzjw.cn&quot;</span>);</span><br><span class="line">        System.out.println(map.get(<span class="number">0</span>));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="NonNull"><a href="#NonNull" class="headerlink" title="@NonNull"></a>@NonNull</h3><p>在方法上使用 <code>@NonNull</code> 注解可以做非空判断，如果传入空值的话会直接抛出 <code>NullPointerException</code> （俗称空指针）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LombokDemo</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">LombokDemo</span>(<span class="string">&quot;garvey&quot;</span>);</span><br><span class="line">        <span class="comment">// 绝对会抛出NullPointerException异常</span></span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">LombokDemo</span>(<span class="literal">null</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">LombokDemo</span><span class="params">(<span class="meta">@NonNull</span> String name)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后会在构造器中添加非空判断，具体代码如下。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LombokDemo</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">LombokDemo</span>(<span class="string">&quot;garvey&quot;</span>);</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">LombokDemo</span>((String)<span class="literal">null</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">LombokDemo</span><span class="params">(<span class="meta">@NonNull</span> String name)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (name == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">NullPointerException</span>(<span class="string">&quot;name is marked non-null but is null&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="built_in">this</span>.name = name;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Cleanup"><a href="#Cleanup" class="headerlink" title="@Cleanup"></a>@Cleanup</h3><p>当我们在 Java 中使用资源时，不可避免地需要在使用后关闭资源。使用 <code>@Cleanup</code> 注解可自动关闭资源。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">str</span> <span class="operator">=</span> <span class="string">&quot;garvey&quot;</span>;</span><br><span class="line">    <span class="comment">// 使用输入输出流自动关闭，无需编写 try catch 和调用 close() 方法</span></span><br><span class="line">    <span class="meta">@Cleanup</span> <span class="type">ByteArrayInputStream</span> <span class="variable">in</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ByteArrayInputStream</span>(str.getBytes(<span class="string">&quot;UTF-8&quot;</span>));</span><br><span class="line">    <span class="meta">@Cleanup</span> <span class="type">ByteArrayOutputStream</span> <span class="variable">out</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ByteArrayOutputStream</span>();</span><br><span class="line">    <span class="type">byte</span>[] b = <span class="keyword">new</span> <span class="title class_">byte</span>[<span class="number">1024</span>];</span><br><span class="line">    <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">r</span> <span class="operator">=</span> in.read(b);</span><br><span class="line">        <span class="keyword">if</span> (r == -<span class="number">1</span>) <span class="keyword">break</span>;</span><br><span class="line">        out.write(b, <span class="number">0</span>, r);</span><br><span class="line">    &#125;</span><br><span class="line">    System.out.println(out.toString(<span class="string">&quot;UTF-8&quot;</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">str</span> <span class="operator">=</span> <span class="string">&quot;garvey&quot;</span>;</span><br><span class="line">    <span class="type">ByteArrayInputStream</span> <span class="variable">in</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ByteArrayInputStream</span>(inStr.getBytes(<span class="string">&quot;UTF-8&quot;</span>));</span><br><span class="line"></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="type">ByteArrayOutputStream</span> <span class="variable">out</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ByteArrayOutputStream</span>();</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">byte</span>[] b = <span class="keyword">new</span> <span class="title class_">byte</span>[<span class="number">1024</span>];</span><br><span class="line"></span><br><span class="line">            <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">                <span class="type">int</span> <span class="variable">r</span> <span class="operator">=</span> in.read(b);</span><br><span class="line">                <span class="keyword">if</span> (r == -<span class="number">1</span>) &#123;</span><br><span class="line">                    System.out.println(out.toString(<span class="string">&quot;UTF-8&quot;</span>););</span><br><span class="line">                    <span class="keyword">return</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                out.write(b, <span class="number">0</span>, r);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (Collections.singletonList(out).get(<span class="number">0</span>) != <span class="literal">null</span>) &#123;</span><br><span class="line">                out.close();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (Collections.singletonList(in).get(<span class="number">0</span>) != <span class="literal">null</span>) &#123;</span><br><span class="line">            in.close();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Getter-Setter"><a href="#Getter-Setter" class="headerlink" title="@Getter/@Setter"></a>@Getter/@Setter</h3><p>有了 @Getter 和 @Setter 注解，我们再也不用编写 getter and setter 方法了。</p><p>其实写 getter 和 setter 方法也不是麻烦事，因为 IDEA 自动生成 getter and setter 方法</p><p>麻烦的是如果类属性的类型和名称改了的话，又要重新生成 getter and setter 方法，这就很头疼</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="meta">@Getter</span></span><br><span class="line">    <span class="meta">@Setter</span></span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="meta">@Getter</span></span><br><span class="line">    <span class="meta">@Setter(AccessLevel.PROTECTED)</span></span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">Student</span> <span class="variable">student</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>();</span><br><span class="line">        student.setName(<span class="string">&quot;garvey&quot;</span>);</span><br><span class="line">        student.setAge(<span class="number">20</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;name=&quot;</span> + student.getName() + <span class="string">&quot;\nage=&quot;</span> + student.getAge());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Student</span> <span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">getName</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">this</span>.name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(<span class="keyword">final</span> String name)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> Integer <span class="title function_">getAge</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">this</span>.age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">setAge</span><span class="params">(<span class="keyword">final</span> Integer age)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="ToString"><a href="#ToString" class="headerlink" title="@ToString"></a>@ToString</h3><p>使用 <code>@ToString</code> 注解可以自动生成 toString 方法，默认会包含所有类属性，使用 <code>@ToString.Exclude</code> 注解可以排除属性的生成。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ToString</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@ToString</span>.Exclude</span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Student</span><span class="params">(Long id, String name, Integer age)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.id = id;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">        <span class="built_in">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">Student</span> <span class="variable">student</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="number">1L</span>, <span class="string">&quot;garvey&quot;</span>, <span class="number">20</span>);</span><br><span class="line">        <span class="comment">// 自动实现toString方法，输出ToStringExample(name=garvey, age=20)</span></span><br><span class="line">        System.out.println(student);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Student</span> <span class="params">(Long id, String name, Integer age)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.id = id;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">        <span class="built_in">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">toString</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;Student(name=&quot;</span> + <span class="built_in">this</span>.name + <span class="string">&quot;, age=&quot;</span> + <span class="built_in">this</span>.age + <span class="string">&quot;)&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="EqualsAndHashCode"><a href="#EqualsAndHashCode" class="headerlink" title="@EqualsAndHashCode"></a>@EqualsAndHashCode</h3><p>使用 <code>@EqualsAndHashCode</code> 注解可以自动生成 <code>hashCode</code> 和 <code>equals</code> 方法，默认包含所有类属性，使用 <code>@EqualsAndHashCode.Exclude</code>可以排除属性的生成。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Getter</span></span><br><span class="line"><span class="meta">@Setter</span></span><br><span class="line"><span class="meta">@EqualsAndHashCode</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line">    <span class="meta">@EqualsAndHashCode</span>.Exclude</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@EqualsAndHashCode</span>.Exclude</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">Student</span> <span class="variable">student</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>();</span><br><span class="line">        student.setId(<span class="number">1L</span>);</span><br><span class="line">        student.setName(<span class="string">&quot;garvey&quot;</span>);</span><br><span class="line">        student.setAge(<span class="number">20</span>);</span><br><span class="line">        <span class="type">Student</span> <span class="variable">student2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>();</span><br><span class="line">        student2.setId(<span class="number">1L</span>);</span><br><span class="line">        <span class="comment">// equals方法只对比id，so 返回true</span></span><br><span class="line">        System.out.println(student.equals(student2));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Student</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">equals</span><span class="params">(<span class="keyword">final</span> Object o)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (o == <span class="built_in">this</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!(o <span class="keyword">instanceof</span> Student)) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="type">Student</span> <span class="variable">other</span> <span class="operator">=</span> (Student)o;</span><br><span class="line">            <span class="keyword">if</span> (!other.canEqual(<span class="built_in">this</span>)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="type">Object</span> <span class="variable">this$id</span> <span class="operator">=</span> <span class="built_in">this</span>.getId();</span><br><span class="line">                <span class="type">Object</span> <span class="variable">other$id</span> <span class="operator">=</span> other.getId();</span><br><span class="line">                <span class="keyword">if</span> (<span class="built_in">this</span>$id == <span class="literal">null</span>) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (other$id != <span class="literal">null</span>) &#123;</span><br><span class="line">                        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="built_in">this</span>$id.equals(other$id)) &#123;</span><br><span class="line">                    <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">protected</span> <span class="type">boolean</span> <span class="title function_">canEqual</span><span class="params">(<span class="keyword">final</span> Object other)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> other <span class="keyword">instanceof</span> Student;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">hashCode</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">PRIME</span> <span class="operator">=</span> <span class="literal">true</span>;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line">        <span class="type">Object</span> <span class="variable">$id</span> <span class="operator">=</span> <span class="built_in">this</span>.getId();</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> result * <span class="number">59</span> + ($id == <span class="literal">null</span> ? <span class="number">43</span> : $id.hashCode());</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="XxConstructor"><a href="#XxConstructor" class="headerlink" title="@XxConstructor"></a>@XxConstructor</h3><p>使用 <code>@XxConstructor</code> 注解可以自动生成构造方法，有 <code>@NoArgsConstructor</code>、 <code>@RequiredArgsConstructor</code> 和 <code>@AllArgsConstructor</code> 三个注解可以使用。</p><ul><li>@NoArgsConstructor：生成无参构造函数。</li><li>@RequiredArgsConstructor：生成包含必须参数的构造函数，使用 @NonNull 注解的类属性为必须参数。</li><li>@AllArgsConstructor：生成包含所有参数的构造函数。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@RequiredArgsConstructor(staticName = &quot;of&quot;)</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="meta">@NonNull</span></span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 无参构造器</span></span><br><span class="line">        <span class="type">Student</span> <span class="variable">student1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>();</span><br><span class="line">        <span class="comment">// 全部参数构造器</span></span><br><span class="line">        <span class="type">Student</span> <span class="variable">student2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="number">1L</span>, <span class="string">&quot;garvey&quot;</span>, <span class="number">20</span>);</span><br><span class="line">        <span class="comment">// @NonNull注解的必须参数构造器</span></span><br><span class="line">        <span class="type">Student</span> <span class="variable">student3</span> <span class="operator">=</span> Student.of(<span class="number">1L</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="meta">@NonNull</span></span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Student</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="title function_">Student</span><span class="params">(<span class="meta">@NonNull</span> <span class="keyword">final</span> Long id)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (id == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">NullPointerException</span>(<span class="string">&quot;id is marked non-null but is null&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="built_in">this</span>.id = id;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> Student <span class="title function_">of</span><span class="params">(<span class="meta">@NonNull</span> <span class="keyword">final</span> Long id)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Student</span>(id);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Student</span><span class="params">(<span class="meta">@NonNull</span> <span class="keyword">final</span> Long id, <span class="keyword">final</span> String name, <span class="keyword">final</span> Integer age)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (id == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">NullPointerException</span>(<span class="string">&quot;id is marked non-null but is null&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="built_in">this</span>.id = id;</span><br><span class="line">            <span class="built_in">this</span>.name = name;</span><br><span class="line">            <span class="built_in">this</span>.age = age;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Data"><a href="#Data" class="headerlink" title="@Data"></a>@Data</h3><p><code>@Data</code> 是一个方便使用的组合注解，是 <code>@ToString</code>、<code>@EqualsAndHashCode</code>、<code>@Getter</code>、<code>@Setter</code> 和 <code>@RequiredArgsConstructor</code> 的组合体。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="meta">@NonNull</span></span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line">    <span class="meta">@EqualsAndHashCode</span>.Exclude</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="meta">@EqualsAndHashCode</span>.Exclude</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// @RequiredArgsConstructor已生效</span></span><br><span class="line">        <span class="type">Student</span> <span class="variable">student1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="number">1L</span>);</span><br><span class="line">        <span class="comment">// @Getter @Setter已生效</span></span><br><span class="line">        student1.setName(<span class="string">&quot;garvey&quot;</span>);</span><br><span class="line">        student1.setAge(<span class="number">20</span>);</span><br><span class="line">        <span class="comment">// @ToString已生效</span></span><br><span class="line">        System.out.println(student1);</span><br><span class="line">        <span class="type">Student</span> <span class="variable">student2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="number">1L</span>);</span><br><span class="line">        <span class="comment">// @EqualsAndHashCode已生效</span></span><br><span class="line">        System.out.println(student1.equals(student2));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="meta">@NonNull</span></span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Student</span><span class="params">(<span class="meta">@NonNull</span> <span class="keyword">final</span> Long id)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (id == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">NullPointerException</span>(<span class="string">&quot;id is marked non-null but is null&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="built_in">this</span>.id = id;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@NonNull</span></span><br><span class="line">    <span class="keyword">public</span> Long <span class="title function_">getId</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">this</span>.id;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">getName</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">this</span>.name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> Integer <span class="title function_">getAge</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">this</span>.age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setId</span><span class="params">(<span class="meta">@NonNull</span> <span class="keyword">final</span> Long id)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (id == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">NullPointerException</span>(<span class="string">&quot;id is marked non-null but is null&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="built_in">this</span>.id = id;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(<span class="keyword">final</span> String name)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setAge</span><span class="params">(<span class="keyword">final</span> Integer age)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">equals</span><span class="params">(<span class="keyword">final</span> Object o)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (o == <span class="built_in">this</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!(o <span class="keyword">instanceof</span> Student)) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="type">Student</span> <span class="variable">other</span> <span class="operator">=</span> (Student)o;</span><br><span class="line">            <span class="keyword">if</span> (!other.canEqual(<span class="built_in">this</span>)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="type">Object</span> <span class="variable">this$id</span> <span class="operator">=</span> <span class="built_in">this</span>.getId();</span><br><span class="line">                <span class="type">Object</span> <span class="variable">other$id</span> <span class="operator">=</span> other.getId();</span><br><span class="line">                <span class="keyword">if</span> (<span class="built_in">this</span>$id == <span class="literal">null</span>) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (other$id != <span class="literal">null</span>) &#123;</span><br><span class="line">                        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="built_in">this</span>$id.equals(other$id)) &#123;</span><br><span class="line">                    <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">protected</span> <span class="type">boolean</span> <span class="title function_">canEqual</span><span class="params">(<span class="keyword">final</span> Object other)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> other <span class="keyword">instanceof</span> Student;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">hashCode</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">PRIME</span> <span class="operator">=</span> <span class="literal">true</span>;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line">        <span class="type">Object</span> <span class="variable">$id</span> <span class="operator">=</span> <span class="built_in">this</span>.getId();</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> result * <span class="number">59</span> + ($id == <span class="literal">null</span> ? <span class="number">43</span> : $id.hashCode());</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">toString</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;Student(id=&quot;</span> + <span class="built_in">this</span>.getId() + <span class="string">&quot;, name=&quot;</span> + <span class="built_in">this</span>.getName() + <span class="string">&quot;, age=&quot;</span> + <span class="built_in">this</span>.getAge() + <span class="string">&quot;)&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Value"><a href="#Value" class="headerlink" title="@Value"></a>@Value</h3><p>使用 @Value 注解可以把类声明为不可变的，声明后此类相当于 <code>final</code> 类，无法被继承，其属性也会变成 <code>final</code> 属性。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Value</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 只能使用全参构造器</span></span><br><span class="line">        <span class="type">Student</span> <span class="variable">student</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="number">1L</span>,<span class="string">&quot;garvey&quot;</span>,<span class="number">20</span>);</span><br><span class="line">        <span class="comment">// student.setName(&quot;garvey&quot;) // 没有生成setter方法，会报错</span></span><br><span class="line">        <span class="comment">// student.name=&quot;garvey&quot;    // 字段被设置为final类型，会报错</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> Long id;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> String name;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="number">1L</span>, <span class="string">&quot;garvey&quot;</span>, <span class="number">20</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Student</span><span class="params">(<span class="keyword">final</span> Long id, <span class="keyword">final</span> String name, <span class="keyword">final</span> Integer age)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.id = id;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">        <span class="built_in">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> Long <span class="title function_">getId</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">this</span>.id;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">getName</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">this</span>.name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> Integer <span class="title function_">getAge</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">this</span>.age;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Builder"><a href="#Builder" class="headerlink" title="@Builder"></a>@Builder</h3><p>使用 <code>@Builder</code> 注解可以通过建造者模式来创建对象，建造者模式加链式调用，创建对象太方便了！</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Builder</span></span><br><span class="line"><span class="meta">@ToString</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line"><span class="keyword">private</span> Long id;</span><br><span class="line"><span class="keyword">private</span> String name;</span><br><span class="line"><span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"><span class="type">Student</span> <span class="variable">student</span> <span class="operator">=</span> Student.builder()</span><br><span class="line">.id(<span class="number">1L</span>)</span><br><span class="line">.name(<span class="string">&quot;garvey&quot;</span>)</span><br><span class="line">.age(<span class="number">20</span>)</span><br><span class="line">.build();</span><br><span class="line">System.out.println(student);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line"><span class="keyword">private</span> Long id;</span><br><span class="line"><span class="keyword">private</span> String name;</span><br><span class="line"><span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">Student(<span class="keyword">final</span> Long id, <span class="keyword">final</span> String name, <span class="keyword">final</span> Integer age) &#123;</span><br><span class="line"><span class="built_in">this</span>.id = id;</span><br><span class="line"><span class="built_in">this</span>.name = name;</span><br><span class="line"><span class="built_in">this</span>.age = age;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> Student.BuilderExampleBuilder <span class="title function_">builder</span><span class="params">()</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Student</span>.BuilderExampleBuilder();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">toString</span><span class="params">()</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="string">&quot;Student(id=&quot;</span> + <span class="built_in">this</span>.id + <span class="string">&quot;, name=&quot;</span> + <span class="built_in">this</span>.name + <span class="string">&quot;, age=&quot;</span> + <span class="built_in">this</span>.age + <span class="string">&quot;)&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">BuilderExampleBuilder</span> &#123;</span><br><span class="line"><span class="keyword">private</span> Long id;</span><br><span class="line"><span class="keyword">private</span> String name;</span><br><span class="line"><span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">BuilderExampleBuilder() &#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> Student.BuilderExampleBuilder <span class="title function_">id</span><span class="params">(<span class="keyword">final</span> Long id)</span> &#123;</span><br><span class="line"><span class="built_in">this</span>.id = id;</span><br><span class="line"><span class="keyword">return</span> <span class="built_in">this</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> Student.BuilderExampleBuilder <span class="title function_">name</span><span class="params">(<span class="keyword">final</span> String name)</span> &#123;</span><br><span class="line"><span class="built_in">this</span>.name = name;</span><br><span class="line"><span class="keyword">return</span> <span class="built_in">this</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> Student.BuilderExampleBuilder <span class="title function_">age</span><span class="params">(<span class="keyword">final</span> Integer age)</span> &#123;</span><br><span class="line"><span class="built_in">this</span>.age = age;</span><br><span class="line"><span class="keyword">return</span> <span class="built_in">this</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> Student <span class="title function_">build</span><span class="params">()</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Student</span>(<span class="built_in">this</span>.id, <span class="built_in">this</span>.name, <span class="built_in">this</span>.age);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">toString</span><span class="params">()</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="string">&quot;Student.BuilderExampleBuilder(id=&quot;</span> + <span class="built_in">this</span>.id + <span class="string">&quot;, name=&quot;</span> + <span class="built_in">this</span>.name + <span class="string">&quot;, age=&quot;</span> + <span class="built_in">this</span>.age + <span class="string">&quot;)&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="SneakyThrows"><a href="#SneakyThrows" class="headerlink" title="@SneakyThrows"></a>@SneakyThrows</h3><p>还在手动捕获并抛出异常？使用 <code>@SneakyThrows</code> 注解自动实现试试！</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 自动抛出异常，无需处理</span></span><br><span class="line">    <span class="meta">@SneakyThrows(UnsupportedEncodingException.class)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">byte</span>[] str2byte(String str) &#123;</span><br><span class="line">        <span class="keyword">return</span> str.getBytes(<span class="string">&quot;UTF-8&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">str</span> <span class="operator">=</span> <span class="string">&quot;garvey&quot;</span>;</span><br><span class="line">        System.out.println(str2byte(str).length);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Student</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">byte</span>[] str2byte(String str) &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> str.getBytes(<span class="string">&quot;UTF-8&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (UnsupportedEncodingException var2) &#123;</span><br><span class="line">            <span class="keyword">throw</span> var2;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Synchronized"><a href="#Synchronized" class="headerlink" title="@Synchronized"></a>@Synchronized</h3><p>当我们在多个线程中访问同一资源时，往往会出现线程安全问题，以前我们往往使用 synchronized 关键字修饰方法来实现同步访问。使用 @Synchronized 注解同样可以实现同步访问。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SynchronizedExample</span> &#123;</span><br><span class="line">    <span class="meta">@NonNull</span></span><br><span class="line">    <span class="keyword">private</span> Integer count;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Synchronized</span></span><br><span class="line">    <span class="meta">@SneakyThrows</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">reduceCount</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (count &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            Thread.sleep(<span class="number">500</span>);</span><br><span class="line">            count--;</span><br><span class="line">            System.out.println(String.format(<span class="string">&quot;thread-%d count:%d&quot;</span>, id, count));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 添加@Synchronized三个线程可以同步调用reduceCount方法</span></span><br><span class="line">        <span class="type">SynchronizedExample</span> <span class="variable">example</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SynchronizedExample</span>(<span class="number">20</span>);</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">ReduceThread</span>(<span class="number">1</span>, example).start();</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">ReduceThread</span>(<span class="number">2</span>, example).start();</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">ReduceThread</span>(<span class="number">3</span>, example).start();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequiredArgsConstructor</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">ReduceThread</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line">        <span class="meta">@NonNull</span></span><br><span class="line">        <span class="keyword">private</span> Integer id;</span><br><span class="line">        <span class="meta">@NonNull</span></span><br><span class="line">        <span class="keyword">private</span> SynchronizedExample example;</span><br><span class="line"></span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">            <span class="keyword">while</span> (example.getCount() &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                example.reduceCount(id);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SynchronizedExample</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="type">Object</span> <span class="variable">$lock</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Object</span>[<span class="number">0</span>];</span><br><span class="line">    <span class="meta">@NonNull</span></span><br><span class="line">    <span class="keyword">private</span> Integer count;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">reduceCount</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">synchronized</span>(<span class="built_in">this</span>.$lock) &#123;</span><br><span class="line">                <span class="keyword">if</span> (<span class="built_in">this</span>.count &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                    Thread.sleep(<span class="number">500L</span>);</span><br><span class="line">                    <span class="type">Integer</span> <span class="variable">var3</span> <span class="operator">=</span> <span class="built_in">this</span>.count;</span><br><span class="line">                    <span class="type">Integer</span> <span class="variable">var4</span> <span class="operator">=</span> <span class="built_in">this</span>.count = <span class="built_in">this</span>.count - <span class="number">1</span>;</span><br><span class="line">                    System.out.println(String.format(<span class="string">&quot;thread-%d count:%d&quot;</span>, id, <span class="built_in">this</span>.count));</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Throwable var7) &#123;</span><br><span class="line">            <span class="keyword">throw</span> var7;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="With"><a href="#With" class="headerlink" title="@With"></a>@With</h3><p>使用 @With 注解可以实现对原对象进行克隆，并改变其一个属性，使用时需要指定全参构造方法。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@With</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WithExample</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">WithExample</span> <span class="variable">example1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">WithExample</span>(<span class="number">1L</span>, <span class="string">&quot;garvey&quot;</span>, <span class="number">20</span>);</span><br><span class="line">        <span class="type">WithExample</span> <span class="variable">example2</span> <span class="operator">=</span> example1.withAge(<span class="number">22</span>);</span><br><span class="line">        <span class="comment">// 将原对象进行clone并设置age，返回false</span></span><br><span class="line">        System.out.println(example1.equals(example2));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WithExample</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> WithExample <span class="title function_">withId</span><span class="params">(<span class="keyword">final</span> Long id)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">this</span>.id == id ? <span class="built_in">this</span> : <span class="keyword">new</span> <span class="title class_">WithExample</span>(id, <span class="built_in">this</span>.name, <span class="built_in">this</span>.age);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> WithExample <span class="title function_">withName</span><span class="params">(<span class="keyword">final</span> String name)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">this</span>.name == name ? <span class="built_in">this</span> : <span class="keyword">new</span> <span class="title class_">WithExample</span>(<span class="built_in">this</span>.id, name, <span class="built_in">this</span>.age);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> WithExample <span class="title function_">withAge</span><span class="params">(<span class="keyword">final</span> Integer age)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">this</span>.age == age ? <span class="built_in">this</span> : <span class="keyword">new</span> <span class="title class_">WithExample</span>(<span class="built_in">this</span>.id, <span class="built_in">this</span>.name, age);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">WithExample</span><span class="params">(<span class="keyword">final</span> Long id, <span class="keyword">final</span> String name, <span class="keyword">final</span> Integer age)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.id = id;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">        <span class="built_in">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Getter-lazy-true"><a href="#Getter-lazy-true" class="headerlink" title="@Getter(lazy=true)"></a>@Getter(lazy=true)</h3><p>当我们获取某一个属性比较消耗资源时，可以给 @Getter 添加 <code>lazy=true</code> 属性实现懒加载，会生成 <code>Double Check Lock</code> 样板代码对属性进行懒加载。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GetterLazyExample</span> &#123;</span><br><span class="line">    <span class="meta">@Getter(lazy = true)</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="type">double</span>[] cached = expensive();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">double</span>[] expensive() &#123;</span><br><span class="line">        <span class="type">double</span>[] result = <span class="keyword">new</span> <span class="title class_">double</span>[<span class="number">1000000</span>];</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; result.length; i++) &#123;</span><br><span class="line">            result[i] = Math.asin(i);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 使用Double Check Lock 样板代码对属性进行懒加载</span></span><br><span class="line">        <span class="type">GetterLazyExample</span> <span class="variable">example</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">GetterLazyExample</span>();</span><br><span class="line">        System.out.println(example.getCached().length);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GetterLazyExample</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> AtomicReference&lt;Object&gt; cached = <span class="keyword">new</span> <span class="title class_">AtomicReference</span>();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">GetterLazyExample</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">double</span>[] expensive() &#123;</span><br><span class="line">        <span class="type">double</span>[] result = <span class="keyword">new</span> <span class="title class_">double</span>[<span class="number">1000000</span>];</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; result.length; ++i) &#123;</span><br><span class="line">            result[i] = Math.asin((<span class="type">double</span>)i);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">double</span>[] getCached() &#123;</span><br><span class="line">        <span class="type">Object</span> <span class="variable">value</span> <span class="operator">=</span> <span class="built_in">this</span>.cached.get();</span><br><span class="line">        <span class="keyword">if</span> (value == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">synchronized</span>(<span class="built_in">this</span>.cached) &#123;</span><br><span class="line">                value = <span class="built_in">this</span>.cached.get();</span><br><span class="line">                <span class="keyword">if</span> (value == <span class="literal">null</span>) &#123;</span><br><span class="line">                    <span class="type">double</span>[] actualValue = <span class="built_in">this</span>.expensive();</span><br><span class="line">                    value = actualValue == <span class="literal">null</span> ? <span class="built_in">this</span>.cached : actualValue;</span><br><span class="line">                    <span class="built_in">this</span>.cached.set(value);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> (<span class="type">double</span>[])((<span class="type">double</span>[])(value == <span class="built_in">this</span>.cached ? <span class="literal">null</span> : value));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Log"><a href="#Log" class="headerlink" title="@Log"></a>@Log</h3><p>使用 @Log 注解，可以直接生成日志对象 log，通过 log 对象可以直接打印日志。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Log</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogExample</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        log.info(<span class="string">&quot;level info&quot;</span>);</span><br><span class="line">        log.warning(<span class="string">&quot;level warning&quot;</span>);</span><br><span class="line">        log.severe(<span class="string">&quot;level severe&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogExample</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Logger</span> <span class="variable">log</span> <span class="operator">=</span> Logger.getLogger(LogExample.class.getName());</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">LogExample</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        log.info(<span class="string">&quot;level info&quot;</span>);</span><br><span class="line">        log.warning(<span class="string">&quot;level warning&quot;</span>);</span><br><span class="line">        log.severe(<span class="string">&quot;level severe&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Slf4j"><a href="#Slf4j" class="headerlink" title="@Slf4j"></a>@Slf4j</h3><p>使用 Lombok 生成日志对象时，根据使用日志实现的不同，有多种注解可以使用。比如 @Log、@Log4j、@Log4j2、@Slf4j 等。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogSlf4jExample</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        log.info(<span class="string">&quot;level:&#123;&#125;&quot;</span>,<span class="string">&quot;info&quot;</span>);</span><br><span class="line">        log.warn(<span class="string">&quot;level:&#123;&#125;&quot;</span>,<span class="string">&quot;warn&quot;</span>);</span><br><span class="line">        log.error(<span class="string">&quot;level:&#123;&#125;&quot;</span>, <span class="string">&quot;error&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译后 Lombok 会生成如下代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogSlf4jExample</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Logger</span> <span class="variable">log</span> <span class="operator">=</span> LoggerFactory.getLogger(LogSlf4jExample.class);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">LogSlf4jExample</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        log.info(<span class="string">&quot;level:&#123;&#125;&quot;</span>, <span class="string">&quot;info&quot;</span>);</span><br><span class="line">        log.warn(<span class="string">&quot;level:&#123;&#125;&quot;</span>, <span class="string">&quot;warn&quot;</span>);</span><br><span class="line">        log.error(<span class="string">&quot;level:&#123;&#125;&quot;</span>, <span class="string">&quot;error&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>参考资料</p><ul><li>官方文档：<a href="https://projectlombok.org/features/all">https://projectlombok.org/features/all</a></li><li><a href="https://mp.weixin.qq.com/s/Ys6ksYasfUj7TSCGICHM8w">macrozheng</a></li></ul>]]></content>
    
    
      
      
        
        
    <summary type="html"></summary>
        
      
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Lombok" scheme="https://blog.imzjw.cn/tags/Lombok/"/>
    
  </entry>
  
  <entry>
    <title>Java复习 - MyBatis 快速入门</title>
    <link href="https://blog.imzjw.cn/posts/462a50a9/"/>
    <id>https://blog.imzjw.cn/posts/462a50a9/</id>
    <published>2020-12-23T05:46:13.000Z</published>
    <updated>2020-12-23T05:46:13.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><h3 id="什么是-MyBatis"><a href="#什么是-MyBatis" class="headerlink" title="什么是 MyBatis"></a>什么是 MyBatis</h3><p>MyBatis 是一个使用 Java 编写的持久层框架。<strong>它封装了 JDBC 操作的很多细节，使开发者只需要关注 sql 语句</strong>，而无需关注<strong>注册驱动、创建连接、创建 Statement 等繁杂的过程</strong>。 使用了 <code>ORM</code> 的思想，屏蔽的 <code>JDBC api</code> 底层细节，实现了对结果集的封装。</p><h3 id="三层架构"><a href="#三层架构" class="headerlink" title="三层架构"></a>三层架构</h3><ul><li>表现层：展示数据</li><li>业务层：处理业务需求</li><li>持久层：和数据库交互</li></ul><h3 id="持久化"><a href="#持久化" class="headerlink" title="持久化"></a>持久化</h3><ul><li>持久化就是将程序的数据在<strong>持久状态</strong>和<strong>瞬时状态</strong>转化的过程</li><li>内存：断电即失</li></ul><h3 id="为什么需要-MyBatis"><a href="#为什么需要-MyBatis" class="headerlink" title="为什么需要 MyBatis"></a>为什么需要 MyBatis</h3><ul><li>传统 <code>JDBC</code> 太复杂了，简化形成框架</li><li><code>SQL</code> 和代码分离，提高了可维护性</li></ul><h3 id="持久层技术解决方案"><a href="#持久层技术解决方案" class="headerlink" title="持久层技术解决方案"></a>持久层技术解决方案</h3><ul><li>JDBC</li><li>Spring 和 JdbcTemplate</li><li>Apache 的 DBUtils</li></ul><h3 id="传统-JDBC"><a href="#传统-JDBC" class="headerlink" title="传统 JDBC"></a>传统 JDBC</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">    <span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">    <span class="type">PreparedStatement</span> <span class="variable">preparedStatement</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">    <span class="type">ResultSet</span> <span class="variable">resultSet</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 1.加载数据库驱动</span></span><br><span class="line">        Class.forName(<span class="string">&quot;com.mysql.jdbc.Driver&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 2.通过驱动管理类获取数据库链接</span></span><br><span class="line">        connection = DriverManager.getConnection(<span class="string">&quot;jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8&quot;</span>, <span class="string">&quot;root&quot;</span>, <span class="string">&quot; root&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 3.定义 sql 语句 ? 表示占位符</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;SELECT * FROM user WHERE username = ?&quot;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 4.获取预处理 statement</span></span><br><span class="line">        preparedStatement = connection.prepareStatement(sql);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 5.设置参数，第一个参数为 sql 语句中参数的序号（从 1 开始），第二个参数为设置的参数值</span></span><br><span class="line">        preparedStatement.setString(<span class="number">1</span>, <span class="string">&quot;loveccknbc&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 6.向数据库发出 sql 执行查询，查询出结果集</span></span><br><span class="line">        resultSet = preparedStatement.executeQuery();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 7.遍历查询结果集</span></span><br><span class="line">        <span class="keyword">while</span> (resultSet.next()) &#123;</span><br><span class="line">            System.out.println(resultSet.getString(<span class="string">&quot;id&quot;</span>) + <span class="string">&quot; &quot;</span> + resultSet.getString(<span class="string">&quot;username&quot;</span>));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="comment">// 8.释放资源</span></span><br><span class="line">        <span class="keyword">if</span> (resultSet != <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                resultSet.close();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (preparedStatement != <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                preparedStatement.close();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (connection != <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                connection.close();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="MaBatis-上手"><a href="#MaBatis-上手" class="headerlink" title="MaBatis 上手"></a>MaBatis 上手</h2><p>步骤：搭建环境 –&gt; 导入 MaBatis –&gt; 编写代码 –&gt; 测试</p><h3 id="搭建环境"><a href="#搭建环境" class="headerlink" title="搭建环境"></a>搭建环境</h3><ol><li><p>创建数据库</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> DATABASE mybatis;</span><br><span class="line"></span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> `<span class="keyword">user</span>`(</span><br><span class="line">    id <span class="type">int</span> <span class="keyword">PRIMARY</span> KEY,</span><br><span class="line">    username <span class="type">VARCHAR</span>(<span class="number">10</span>),</span><br><span class="line">    password <span class="type">VARCHAR</span>(<span class="number">10</span>)</span><br><span class="line">);        </span><br><span class="line"></span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `<span class="keyword">user</span>` <span class="keyword">VALUES</span>(<span class="number">1</span>,<span class="string">&#x27;admin&#x27;</span>,<span class="string">&#x27;admin123&#x27;</span>);</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `<span class="keyword">user</span>` <span class="keyword">VALUES</span>(<span class="number">2</span>,<span class="string">&#x27;root&#x27;</span>,<span class="string">&#x27;root123&#x27;</span>);</span><br></pre></td></tr></table></figure></li><li><p>创建 maven 项目</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/462a50a9/image-20201223135718527.webp" alt="img"></p></li><li><p>导入 maven 依赖（<code>pom.xml</code>）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- JUnit --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>junit<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>junit<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.12<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- mybatis --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.5.6<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 数据库驱动 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.1.47<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- lombok --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.18.16<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>开始编写代码</p><p>编写核心配置文件(<code>resources/mybatis-config.xml</code>)</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span> ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">configuration</span></span></span><br><span class="line"><span class="meta">        <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Config 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-config.dtd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--核心配置文件--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">environments</span> <span class="attr">default</span>=<span class="string">&quot;development&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">environment</span> <span class="attr">id</span>=<span class="string">&quot;development&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">transactionManager</span> <span class="attr">type</span>=<span class="string">&quot;JDBC&quot;</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">dataSource</span> <span class="attr">type</span>=<span class="string">&quot;POOLED&quot;</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driver&quot;</span> <span class="attr">value</span>=<span class="string">&quot;com.mysql.jdbc.Driver&quot;</span>/&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;url&quot;</span></span></span><br><span class="line"><span class="tag">                          <span class="attr">value</span>=<span class="string">&quot;jdbc:mysql://localhost:3306/mybatis?useUnicode=true<span class="symbol">&amp;amp;</span>characterEncoding=utf-8<span class="symbol">&amp;amp;</span>serverTimezone=UTC&quot;</span>/&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span> <span class="attr">value</span>=<span class="string">&quot;root&quot;</span>/&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;root&quot;</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">dataSource</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">environment</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">environments</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 每个 Mapper.xml 都要注册在 MyBatis 核心配置文件中--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mappers</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">mapper</span> <span class="attr">resource</span>=<span class="string">&quot;mapper/UserMapper.xml&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">mappers</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>在 <code>resources</code> 下创建 <code>mapper/UserMapper.xml</code></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span> ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">mapper</span></span></span><br><span class="line"><span class="meta">        <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;cn.imzjw.mybatis.mapper.UserMapper&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>编写 Mabatis 工具类（<code>cn.imzjw.mybatis.utils.MybatisUtils.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * sqlSessionFactory生产sqlSession</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> https://blog.imzjw.cn</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2020/12/23 13:42</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MybatisUtils</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 提升作用域</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> SqlSessionFactory sqlSessionFactory;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        <span class="comment">// 使用MaBatis第一步，获取sqlSessionFactory对象</span></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">resource</span> <span class="operator">=</span> <span class="string">&quot;mybatis-config.xml&quot;</span>;</span><br><span class="line">            <span class="type">InputStream</span> <span class="variable">inputStream</span> <span class="operator">=</span> Resources.getResourceAsStream(resource);</span><br><span class="line">            sqlSessionFactory = <span class="keyword">new</span> <span class="title class_">SqlSessionFactoryBuilder</span>().build(inputStream);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">       <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 既然有了SqlSessionFactory，就可以从中获得sqlSession实例。</span></span><br><span class="line"><span class="comment">         * sqlSession完全包含了面向数据库执行SQL命令所需要的所有方法</span></span><br><span class="line"><span class="comment">         *</span></span><br><span class="line"><span class="comment">         * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> SqlSession <span class="title function_">getSqlSession</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> sqlSessionFactory.openSession();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>创建实体类（<code>cn.imzjw.mybatis.entity.User.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> https://blog.imzjw.cn</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2020/12/23 14:09</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">User</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> id;</span><br><span class="line">    <span class="keyword">private</span> String username;</span><br><span class="line">    <span class="keyword">private</span> String password;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>mapper 接口（<code>cn.imzjw.mybatis.mapper.UserMapper.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">UserMapper</span> &#123;</span><br><span class="line">    List&lt;User&gt; <span class="title function_">getUserList</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>接口实现类(<code>resources/mapper/UserMapper.xml</code>)</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span> ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">mapper</span></span></span><br><span class="line"><span class="meta">        <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;cn.imzjw.mybatis.mapper.UserMapper&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--select查询语句--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getUserList&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;cn.imzjw.mybatis.entity.User&quot;</span>&gt;</span></span><br><span class="line">        SELECT * FROM `user`</span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol><h3 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h3><p>在 <code>test</code> 文件下编写测试类（<code>test/java/TestMybatis.java</code>）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> https://blog.imzjw.cn</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2020/12/23 13:40</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestMybatis</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testQuery</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">SqlSession</span> <span class="variable">sqlSession</span> <span class="operator">=</span> MybatisUtils.getSqlSession();</span><br><span class="line">        <span class="type">UserMapper</span> <span class="variable">userMapper</span> <span class="operator">=</span> sqlSession.getMapper(UserMapper.class);</span><br><span class="line"></span><br><span class="line">        userMapper.getUserList().forEach(xiaojia -&gt; System.out.println(xiaojia));</span><br><span class="line"></span><br><span class="line">        sqlSession.close();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>得到结果</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">User(id=<span class="number">1</span>, username=admin, password=admin123)</span><br><span class="line">User(id=<span class="number">2</span>, username=root, password=root123)</span><br></pre></td></tr></table></figure><h4 id="其它问题"><a href="#其它问题" class="headerlink" title="其它问题"></a>其它问题</h4><p>如果出现以下异常</p><div class="note danger flat"><p>Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find </p></div><p>请在 <code>pom.xml</code>  最后加入资源过滤，没异常就忽略</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">resources</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">resource</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">directory</span>&gt;</span>src/main/java<span class="tag">&lt;/<span class="name">directory</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">includes</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">include</span>&gt;</span>**/*.xml<span class="tag">&lt;/<span class="name">include</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">includes</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">filtering</span>&gt;</span>true<span class="tag">&lt;/<span class="name">filtering</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">resource</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br></pre></td></tr></table></figure><p>我的 <code>pom.xml</code> 完整代码</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0&quot;</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>cn.imzjw.mybatis<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>junit<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>junit<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.12<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.5.6<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.1.47<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.18.16<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">resources</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">resource</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">directory</span>&gt;</span>src/main/java<span class="tag">&lt;/<span class="name">directory</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">includes</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">include</span>&gt;</span>**/*.xml<span class="tag">&lt;/<span class="name">include</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">includes</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">filtering</span>&gt;</span>true<span class="tag">&lt;/<span class="name">filtering</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">resource</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">MyBatis是一个使用Java编写的持久层框架。它封装了JDBC操作的很多细节，使开发者只需要关注sql语句，而无需关注注册驱动、创建连接、创建 Statement 等繁杂的过程。 使用了ORM的思想，屏蔽的JDBC api底层细节，实现了对结果集的封装。</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="MyBatis" scheme="https://blog.imzjw.cn/tags/MyBatis/"/>
    
  </entry>
  
  <entry>
    <title>基于Twikoo评论系统最新版修改添加Qmsg酱</title>
    <link href="https://blog.imzjw.cn/posts/twikoo-qmsg/"/>
    <id>https://blog.imzjw.cn/posts/twikoo-qmsg/</id>
    <published>2020-12-22T12:46:44.000Z</published>
    <updated>2020-12-24T02:30:44.000Z</updated>
    
    <content type="html"><![CDATA[<div class="note danger flat"><p>这篇文章 duck 不必往下看了，我提 <a href="https://github.com/imaegoo/twikoo/pull/68">PR</a> 了，从 Twikoo 0.4.3 开始就支持 QQ 通知了</p></div><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>虽然 Twikoo 自带了有 Server 酱和邮箱通知，可是我大部分时间都挂着企鹅，有时 WeChat 消息我都会忘记看了，因为我用 WeChat 干的最多的事就是拿来 pay，索性就在 Twikoo 版本基础上加了个 Qmsg 酱进行 QQ 通知，奈何没有国外地区，不然就弄 Telegram 通知了！</p><p>注：本篇文章是基于 <a href="https://twikoo.js.org/">Twikoo</a>@<code>0.4.2</code> 版本且Hexo主题 <a href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a>@<code>3.4.1</code> 进行添加Qmsg酱</p><p>关于 Twikoo 的配置可看 Twikoo <a href="https://twikoo.js.org/">官网</a> 也可看我洪哥的这篇 <a href="https://blog.zhheo.com/p/2e6bbbd0.html">Twikoo 评论系统配置教程（基于腾讯云开发）</a></p><h2 id="正式开始"><a href="#正式开始" class="headerlink" title="正式开始"></a>正式开始</h2><p>首先先去 Butterfly 主题下的配置文件(<code>_config.yml</code>)，在最后面 CDN 配置项找到 Twikoo 并将其链接修改成</p><p><del><code>https://cdn.jsdelivr.net/gh/zjwo/CDN@master/js/twikoo.all.min.js</code></del></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/twikoo-qmsg/20201222211934255.webp" alt="img"></p><p>然后就可以在 Twikoo 管理面板看到效果了</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/twikoo-qmsg/image-20201222212132149.webp" height="450" alt="img"><p>接着到 <a href="https://console.cloud.tencent.com/tcb/scf/index">云函数</a>  –&gt; 进入你的函数 –&gt; 最后点击函数代码将 <code>index.js</code> 全部删除</p><p>打开基于 Twikoo 评论系统最新版添加 Qmsg 酱的  <del><a href="https://cdn.jsdelivr.net/gh/zjwo/CDN/js/twikoo/index.js">index.js</a></del>  全选复制</p><p>并粘贴到函数代码 （ index.js ）中</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/twikoo-qmsg/image-20201222214723066.webp" alt="img"></p><p>最后保存，大功告成！！</p><p>Qmsg 酱成功通知</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/twikoo-qmsg/qmsg.webp" alt="img"></p>]]></content>
    
    
    <summary type="html">虽然 Twikoo 自带了有 Server 酱和邮箱通知，可是我大部分时间都挂着企鹅，有时 WeChat 消息我都会忘记看了，因为我用 WeChat 干的最多的事就是拿来 pay</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="Twikoo" scheme="https://blog.imzjw.cn/tags/Twikoo/"/>
    
  </entry>
  
  <entry>
    <title>Java复习 - SSM 整合</title>
    <link href="https://blog.imzjw.cn/posts/ssm-config/"/>
    <id>https://blog.imzjw.cn/posts/ssm-config/</id>
    <published>2020-12-22T03:59:09.000Z</published>
    <updated>2020-12-22T03:59:09.000Z</updated>
    
    <content type="html"><![CDATA[<p>虽然 ssm 整合教程都烂大街了，而我这篇文章也仅仅是我今天做为复习记录一下… 怎么说也踩到坑了(真的太久没配置了)，但是我不会告诉你的，总而言之</p><p>spring boot 真香</p><h2 id="环境要求"><a href="#环境要求" class="headerlink" title="环境要求"></a>环境要求</h2><ul><li>IDEA（2018.3）</li><li>MySQL 5.7</li><li>Tomcat 9.0.31</li><li>Maven 3.6.3</li></ul><h2 id="数据库环境"><a href="#数据库环境" class="headerlink" title="数据库环境"></a>数据库环境</h2><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> IF <span class="keyword">EXISTS</span> `book`;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> `book` (</span><br><span class="line">  `book_id` <span class="type">int</span>(<span class="number">10</span>) <span class="keyword">NOT</span> <span class="keyword">NULL</span> AUTO_INCREMENT COMMENT <span class="string">&#x27;书id&#x27;</span>,</span><br><span class="line">  `book_name` <span class="type">varchar</span>(<span class="number">100</span>) <span class="keyword">NOT</span> <span class="keyword">NULL</span> COMMENT <span class="string">&#x27;书名&#x27;</span>,</span><br><span class="line">  `book_counts` <span class="type">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="keyword">NULL</span> COMMENT <span class="string">&#x27;数量&#x27;</span>,</span><br><span class="line">  `detail` <span class="type">varchar</span>(<span class="number">200</span>) <span class="keyword">NOT</span> <span class="keyword">NULL</span> COMMENT <span class="string">&#x27;描述&#x27;</span>,</span><br><span class="line">  KEY `book_id` (`book_id`)</span><br><span class="line">) ENGINE<span class="operator">=</span>InnoDB AUTO_INCREMENT<span class="operator">=</span><span class="number">25</span> <span class="keyword">DEFAULT</span> CHARSET<span class="operator">=</span>utf8mb4;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- ----------------------------</span></span><br><span class="line"><span class="comment">-- Records of book</span></span><br><span class="line"><span class="comment">-- ----------------------------</span></span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `book` <span class="keyword">VALUES</span> (<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;Java&#x27;</span>, <span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;从入门到放弃&#x27;</span>);</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> `book` <span class="keyword">VALUES</span> (<span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;MySQL&#x27;</span>, <span class="string">&#x27;10&#x27;</span>, <span class="string">&#x27;从删库到跑路&#x27;</span>);</span><br></pre></td></tr></table></figure><h2 id="基本环境搭建"><a href="#基本环境搭建" class="headerlink" title="基本环境搭建"></a>基本环境搭建</h2><p>新建 Maven Web 项目（注意选择，选择没有 22 的 <code>webapp</code> ）</p><p>导入依赖（pom.xml）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>junit<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>junit<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.11<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-webmvc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.3.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-jdbc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.3.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.1.47<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--c3p0--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.mchange<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>c3p0<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>0.9.5.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--start Servlet JSP--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>javax.servlet<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>servlet-api<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.5<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>javax.servlet.jsp<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jsp-api<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>javax.servlet<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jstl<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--end Servlet JSP--&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--Mybatis--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.5.6<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-spring<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.0.6<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--END Mybatis--&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.18.16<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">build</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--Maven资源过滤设置--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">resources</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">resource</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">directory</span>&gt;</span>src/main/java<span class="tag">&lt;/<span class="name">directory</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">includes</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">include</span>&gt;</span>**/*.properties<span class="tag">&lt;/<span class="name">include</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">include</span>&gt;</span>**/*.xml<span class="tag">&lt;/<span class="name">include</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">includes</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">filtering</span>&gt;</span>false<span class="tag">&lt;/<span class="name">filtering</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">resource</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">resource</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">directory</span>&gt;</span>src/main/resources<span class="tag">&lt;/<span class="name">directory</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">includes</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">include</span>&gt;</span>**/*.properties<span class="tag">&lt;/<span class="name">include</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">include</span>&gt;</span>**/*.xml<span class="tag">&lt;/<span class="name">include</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">includes</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">filtering</span>&gt;</span>false<span class="tag">&lt;/<span class="name">filtering</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">resource</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--END Maven资源过滤设置--&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">build</span>&gt;</span></span><br></pre></td></tr></table></figure><p>编写 <code>web.xml</code></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">web-app</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://xmlns.jcp.org/xml/ns/javaee&quot;</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd&quot;</span></span></span><br><span class="line"><span class="tag">         <span class="attr">version</span>=<span class="string">&quot;4.0&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--解决乱码问题--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">filter</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">filter-name</span>&gt;</span>encoding<span class="tag">&lt;/<span class="name">filter-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">filter-class</span>&gt;</span>org.springframework.web.filter.CharacterEncodingFilter<span class="tag">&lt;/<span class="name">filter-class</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">init-param</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>encoding<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>utf-8<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">init-param</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">filter</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">filter-mapping</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">filter-name</span>&gt;</span>encoding<span class="tag">&lt;/<span class="name">filter-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">url-pattern</span>&gt;</span>/*<span class="tag">&lt;/<span class="name">url-pattern</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">filter-mapping</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--注册DispatcherServlet--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">servlet</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">servlet-name</span>&gt;</span>springmvc<span class="tag">&lt;/<span class="name">servlet-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">servlet-class</span>&gt;</span>org.springframework.web.servlet.DispatcherServlet<span class="tag">&lt;/<span class="name">servlet-class</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">init-param</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>contextConfigLocation<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>classpath:spring/spring-web.xml<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">init-param</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--启动级别-1--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">load-on-startup</span>&gt;</span>1<span class="tag">&lt;/<span class="name">load-on-startup</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">servlet</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- /   匹配所有的请求(不包括.jsp)--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- /*  匹配所有的请求(包括.jsp)--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">servlet-mapping</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">servlet-name</span>&gt;</span>springmvc<span class="tag">&lt;/<span class="name">servlet-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">url-pattern</span>&gt;</span>/<span class="tag">&lt;/<span class="name">url-pattern</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">servlet-mapping</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--配置spring容器，tomcat启动时，创建spring容器--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">listener</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">listener-class</span>&gt;</span>org.springframework.web.context.ContextLoaderListener<span class="tag">&lt;/<span class="name">listener-class</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">listener</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context-param</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>contextConfigLocation<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>classpath:spring/spring-*.xml<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">context-param</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">web-app</span>&gt;</span></span><br></pre></td></tr></table></figure><p>在 <code>resources</code> 下新建 <code>db.properties</code> 并加入以下代码</p><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">jdbc.driver</span>=<span class="string">com.mysql.jdbc.Driver</span></span><br><span class="line"><span class="attr">jdbc.url</span>=<span class="string">jdbc:mysql://localhost:3306/ssm?useUnicode=true&amp;amp;characterEncoding=utf-8&amp;amp;serverTimezone=UTC</span></span><br><span class="line"><span class="attr">jdbc.username</span>=<span class="string">root</span></span><br><span class="line"><span class="attr">jdbc.password</span>=<span class="string">root</span></span><br></pre></td></tr></table></figure><p>在 <code>resources</code> 下新建 mybatis 配置文件（mybatis-config.xml）名字随意，但为了规范</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span> ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">configuration</span></span></span><br><span class="line"><span class="meta">        <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Config 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-config.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--配置全局属性--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">settings</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--获取数据库自动增长列--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">setting</span> <span class="attr">name</span>=<span class="string">&quot;useGeneratedKeys&quot;</span> <span class="attr">value</span>=<span class="string">&quot;true&quot;</span>/&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--开启列别名替换列名--&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--&lt;setting name=&quot;useColumnLabel&quot; value=&quot;true&quot;/&gt;--&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--开启驼峰命名--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">setting</span> <span class="attr">name</span>=<span class="string">&quot;mapUnderscoreToCamelCase&quot;</span> <span class="attr">value</span>=<span class="string">&quot;true&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">settings</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--开启别名,可在这配置，也可在spring-dao.xml中配置--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--&lt;typeAliases&gt;--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--&lt;package name=&quot;cn.imzjw.ssm.entity&quot;/&gt;--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--&lt;/typeAliases&gt;--&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br></pre></td></tr></table></figure><p>在 <code>resources</code> 下新建 <code>spring</code> 文件夹</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/ssm-config/image-20201222191555507.webp" alt="img"></p><p>接着在 <code>spring</code> 文件夹下新建 <code>spring-dao.xml</code></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">&quot;http://www.springframework.org/schema/context&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/beans/spring-beans.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/context</span></span></span><br><span class="line"><span class="string"><span class="tag">       https://www.springframework.org/schema/context/spring-context.xsd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- ==============================配置整合mybatis过程============================== --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--===============================配置数据库相关参数属性=============================--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 1.关联数据库文件 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:property-placeholder</span> <span class="attr">location</span>=<span class="string">&quot;classpath:db.properties&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 2.数据库连接池 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.mchange.v2.c3p0.ComboPooledDataSource&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 配置连接池属性 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driverClass&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.driver&#125;&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;jdbcUrl&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.url&#125;&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;user&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.username&#125;&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.password&#125;&quot;</span>/&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- c3p0连接池的私有属性 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;maxPoolSize&quot;</span> <span class="attr">value</span>=<span class="string">&quot;30&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;minPoolSize&quot;</span> <span class="attr">value</span>=<span class="string">&quot;10&quot;</span>/&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 关闭连接后不自动commit --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;autoCommitOnClose&quot;</span> <span class="attr">value</span>=<span class="string">&quot;false&quot;</span>/&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 获取连接超时时间 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;checkoutTimeout&quot;</span> <span class="attr">value</span>=<span class="string">&quot;10000&quot;</span>/&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 当获取连接失败重试次数 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;acquireRetryAttempts&quot;</span> <span class="attr">value</span>=<span class="string">&quot;2&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--3、配置mybatis的sqlSessionFactory--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;sqlSessionFactory&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.mybatis.spring.SqlSessionFactoryBean&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--配置数据源,如果不配置数据源，它如何操作数据库呢--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;dataSource&quot;</span>/&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--自动扫描mapper.xml文件--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;mapperLocations&quot;</span> <span class="attr">value</span>=<span class="string">&quot;classpath:mapper/*Mapper.xml&quot;</span>/&gt;</span> <span class="comment">&lt;!--此处填写你对应的位置--&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--扫描mapper-config文件--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;configLocation&quot;</span> <span class="attr">value</span>=<span class="string">&quot;classpath:mybatis-config.xml&quot;</span>/&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--扫描entity包，使用别名，或者在mybatis-config.xml文件配置，二选一--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;typeAliasesPackage&quot;</span> <span class="attr">value</span>=<span class="string">&quot;cn.imzjw.ssm.entity&quot;</span>/&gt;</span>  <span class="comment">&lt;!--此处填写你自己对应的包名--&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 4.配置扫描Dao接口包，动态实现Dao接口注入到spring容器中 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">&quot;org.mybatis.spring.mapper.MapperScannerConfigurer&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 给出需要扫描Dao接口包 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;basePackage&quot;</span> <span class="attr">value</span>=<span class="string">&quot;cn.imzjw.ssm.mapper&quot;</span>/&gt;</span> <span class="comment">&lt;!--此处填写你自己对应的包名--&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 注入sqlSessionFactory --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;sqlSessionFactoryBeanName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;sqlSessionFactory&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure><p>编写 <code>spring-service.xml</code>（resources / spring / spring-service.xml）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">&quot;http://www.springframework.org/schema/context&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:tx</span>=<span class="string">&quot;http://www.springframework.org/schema/tx&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/beans/spring-beans.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/context</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/context/spring-context.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/tx</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/tx/spring-tx-4.0.xsd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--导入spring-dao文件，目的就是引用数据源--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">import</span> <span class="attr">resource</span>=<span class="string">&quot;spring-dao.xml&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 扫描service包下所有使用注解的类型 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;cn.imzjw.ssm.service&quot;</span>/&gt;</span> <span class="comment">&lt;!--此处填写你自己对应的包名--&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 配置事务管理器 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;transactionManager&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 注入数据库连接池 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;dataSource&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 开启声明式事物 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tx:annotation-driven</span> <span class="attr">transaction-manager</span>=<span class="string">&quot;transactionManager&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure><p><code>spring-web.xml</code>（resources / spring / spring-web.xml）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">&quot;http://www.springframework.org/schema/context&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:mvc</span>=<span class="string">&quot;http://www.springframework.org/schema/mvc&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/mvc</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/beans</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/context</span></span></span><br><span class="line"><span class="string"><span class="tag">       http://www.springframework.org/schema/context/spring-context-4.0.xsd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- =================================配置springmvc================================= --&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 1、开启springMvc注解模式 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mvc:annotation-driven</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;cn.imzjw.ssm.controller&quot;</span>&gt;</span> <span class="comment">&lt;!--此处填写你自己对应的包名--&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--只扫描Controller组件--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">context:include-filter</span> <span class="attr">type</span>=<span class="string">&quot;annotation&quot;</span> <span class="attr">expression</span>=<span class="string">&quot;org.springframework.stereotype.Controller&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--配置视图解析器--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.web.servlet.view.InternalResourceViewResolver&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;prefix&quot;</span> <span class="attr">value</span>=<span class="string">&quot;/WEB-INF/jsp/&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;suffix&quot;</span> <span class="attr">value</span>=<span class="string">&quot;.jsp&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure><p>接着在 resources 下新建 mapper 文件夹，然后不用管他先，如此如此基本的环境就已经搭建好了</p><p>这是我的项目结构</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/ssm-config/image-20201222192814810.webp" alt="img"></p><p>现在开始上代码啦</p><p>实体类 <code>Book</code>（cn.imzjw.ssm.entity.Book.java）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> https://blog.imzjw.cn</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2020/12/21 17:20</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Book</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 书籍编号</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> bookId;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 书籍名称</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String bookName;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 书籍个数</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> bookCounts;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 描述</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String detail;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>mapper </code> 层（cn.imzjw.ssm.mapper.BookMapper.java）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> https://blog.imzjw.cn</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2020/12/21 17:19</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">BookMapper</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 增加书籍</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> book</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="type">int</span> <span class="title function_">addBook</span><span class="params">(Book book)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 删除书籍</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> bookId</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="type">int</span> <span class="title function_">deleteBookById</span><span class="params">(<span class="type">int</span> bookId)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 更新书籍</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> book</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="type">int</span> <span class="title function_">updateBook</span><span class="params">(Book book)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据书籍ID查询</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> bookId</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Book <span class="title function_">selectBookById</span><span class="params">(<span class="type">int</span> bookId)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询全部</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    List&lt;Book&gt; <span class="title function_">selectAllBook</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 搜索</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> bookName</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Book <span class="title function_">selectBookName</span><span class="params">(String bookName)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编写接口对应的 Mapper.xml，在 resources  /  mapper / 新建 <code>BookMapper.xml</code></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span> ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">mapper</span></span></span><br><span class="line"><span class="meta">        <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;cn.imzjw.ssm.mapper.BookMapper&quot;</span>&gt;</span> <span class="comment">&lt;!--此处对应你自己的包名--&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">insert</span> <span class="attr">id</span>=<span class="string">&quot;addBook&quot;</span> <span class="attr">parameterType</span>=<span class="string">&quot;Book&quot;</span>&gt;</span></span><br><span class="line">        INSERT INTO book (book_name, book_counts, detail) VALUES (#&#123;bookName&#125;, #&#123;bookCounts&#125;, #&#123;detail&#125;)</span><br><span class="line">    <span class="tag">&lt;/<span class="name">insert</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">delete</span> <span class="attr">id</span>=<span class="string">&quot;deleteBookById&quot;</span> <span class="attr">parameterType</span>=<span class="string">&quot;int&quot;</span>&gt;</span></span><br><span class="line">        DELETE FROM book WHERE book_id = #&#123;bookId&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">delete</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">update</span> <span class="attr">id</span>=<span class="string">&quot;updateBook&quot;</span> <span class="attr">parameterType</span>=<span class="string">&quot;Book&quot;</span>&gt;</span></span><br><span class="line">        UPDATE book SET book_name = #&#123;bookName&#125;, book_counts = #&#123;bookCounts&#125;, detail = #&#123;detail&#125;</span><br><span class="line">        WHERE book_id = #&#123;bookId&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">update</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;selectBookById&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;Book&quot;</span>&gt;</span></span><br><span class="line">        SELECT * FROM book</span><br><span class="line">        WHERE book_id = #&#123;book_id&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;selectAllBook&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;Book&quot;</span>&gt;</span></span><br><span class="line">      SELECT * FROM book</span><br><span class="line">   <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;selectBookName&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;Book&quot;</span>&gt;</span></span><br><span class="line">        SELECT * FROM book</span><br><span class="line">        WHERE bookName = #&#123;bookName&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure><p><code>service</code>  层（cn.imzjw.ssm.service.BookService.java）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">BookService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 增加书籍</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> book</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="type">int</span> <span class="title function_">addBook</span><span class="params">(Book book)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 删除书籍</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> bookId</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="type">int</span> <span class="title function_">deleteBookById</span><span class="params">(<span class="type">int</span> bookId)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 更新书籍</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> book</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="type">int</span> <span class="title function_">updateBook</span><span class="params">(Book book)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据书籍ID查询</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> bookId</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Book <span class="title function_">selectBookById</span><span class="params">(<span class="type">int</span> bookId)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询全部</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    List&lt;Book&gt; <span class="title function_">selectAllBook</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 搜索</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> bookName</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Book <span class="title function_">selectBookName</span><span class="params">(String bookName)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>service</code> 层实现类（cn.imzjw.ssm.service.impl.BookServiceImpl.java）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> https://blog.imzjw.cn</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2020/12/21 17:29</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BookServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">BookService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> BookMapper bookMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">addBook</span><span class="params">(Book book)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> bookMapper.addBook(book);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">deleteBookById</span><span class="params">(<span class="type">int</span> bookId)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> bookMapper.deleteBookById(bookId);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">updateBook</span><span class="params">(Book book)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> bookMapper.updateBook(book);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Book <span class="title function_">selectBookById</span><span class="params">(<span class="type">int</span> bookId)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> bookMapper.selectBookById(bookId);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> List&lt;Book&gt; <span class="title function_">selectAllBook</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> bookMapper.selectAllBook();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Book <span class="title function_">selectBookName</span><span class="params">(String bookName)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> bookMapper.selectBookName(bookName);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>controller</code> 层（cn.imzjw.ssm.controller.BookController.java）</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> https://blog.imzjw.cn</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2020/12/21 17:20</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BookController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> BookService bookService;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 启动Tomcat的时候，直接重定向到所有书籍列表</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;/&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">index</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;redirect:listBook&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询全部书籍，并且返回到一个书籍展示页面</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> model</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;listBook&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">list</span><span class="params">(Model model)</span> &#123;</span><br><span class="line">        model.addAttribute(<span class="string">&quot;list&quot;</span>, bookService.selectAllBook());</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;allBook&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 跳转到增加书籍页面</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;/toAddBook&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">toAddPaper</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;addBook&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 添加书籍</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> book</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@PostMapping(&quot;/addBook&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">addBook</span><span class="params">(Book book)</span> &#123;</span><br><span class="line">        bookService.addBook(book);</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;redirect:listBook&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 跳转到修改页面</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> id</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> model</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;/toUpdate&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">toUpdatePaper</span><span class="params">(<span class="type">int</span> id, Model model)</span> &#123;</span><br><span class="line">        model.addAttribute(<span class="string">&quot;toBook&quot;</span>, bookService.selectBookById(id));</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;updateBook&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 修改书籍</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> book</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@PostMapping(&quot;/updateBook&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">updateBook</span><span class="params">(Book book)</span> &#123;</span><br><span class="line">        bookService.updateBook(book);</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;redirect:listBook&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 删除书籍</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> id</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;delBook&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">delBook</span><span class="params">(<span class="type">int</span> id)</span> &#123;</span><br><span class="line">        bookService.deleteBookById(id);</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;redirect:listBook&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询书籍</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> selectBookName</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> model</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;/selectBook&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">selectBook</span><span class="params">(String selectBookName, Model model)</span> &#123;</span><br><span class="line">        <span class="type">Book</span> <span class="variable">book</span> <span class="operator">=</span> bookService.selectBookName(selectBookName);</span><br><span class="line">        List&lt;Book&gt; list = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">        list.add(book);</span><br><span class="line">        <span class="keyword">if</span> (book == <span class="literal">null</span>) &#123;</span><br><span class="line">            model.addAttribute(<span class="string">&quot;error&quot;</span>, <span class="string">&quot;*未查询到相关数据&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        model.addAttribute(<span class="string">&quot;list&quot;</span>, list);</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;allBook&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>接着在 <code>WEB-INF</code> 下新建 <code>jsp 文件夹</code>，然后在 <code>jsp</code> 文件夹新建 <code>allBook.jsp</code>（书籍展示页面）</p><figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ taglib prefix=<span class="string">&quot;c&quot;</span> uri=<span class="string">&quot;http://java.sun.com/jsp/jstl/core&quot;</span> %&gt;</span><br><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;title&gt;书籍展示&lt;/title&gt;</span><br><span class="line">    &lt;%--引入BootStrap--%&gt;</span><br><span class="line">    &lt;link rel=<span class="string">&quot;stylesheet&quot;</span> href=<span class="string">&quot;https://npm.elemecdn.com/bootstrap@3.3.7/dist/css/bootstrap.min.css&quot;</span></span><br><span class="line">          integrity=<span class="string">&quot;sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u&quot;</span> crossorigin=<span class="string">&quot;anonymous&quot;</span>&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line"></span><br><span class="line">&lt;div class=<span class="string">&quot;container&quot;</span>&gt;</span><br><span class="line">    &lt;div class=<span class="string">&quot;row clearfix&quot;</span>&gt;</span><br><span class="line">        &lt;div class=<span class="string">&quot;col-md-12 column&quot;</span>&gt;</span><br><span class="line">            &lt;div class=<span class="string">&quot;page-header text-center&quot;</span>&gt;</span><br><span class="line">                &lt;h1&gt;</span><br><span class="line">                    &lt;small&gt;书籍管理系统&lt;/small&gt;</span><br><span class="line">                &lt;/h1&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line"></span><br><span class="line">    &lt;div class=<span class="string">&quot;row&quot;</span>&gt;</span><br><span class="line">        &lt;div class=<span class="string">&quot;col-md-4 column&quot;</span>&gt;</span><br><span class="line">            &lt;a class=<span class="string">&quot;btn btn-default&quot;</span> href=<span class="string">&quot;$&#123;pageContext.request.contextPath&#125;/listBook&quot;</span>&gt;显示全部&lt;/a&gt;</span><br><span class="line">            &lt;a class=<span class="string">&quot;btn btn-default&quot;</span> href=<span class="string">&quot;$&#123;pageContext.request.contextPath&#125;/toAddBook&quot;</span>&gt;新增书籍&lt;/a&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line"></span><br><span class="line">        &lt;form action=<span class="string">&quot;$&#123;pageContext.request.contextPath&#125;/selectBook&quot;</span> method=<span class="string">&quot;post&quot;</span>&gt;</span><br><span class="line">            &lt;div class=<span class="string">&quot;input-group col-md-3&quot;</span> style=<span class="string">&quot;float: right&quot;</span>&gt;</span><br><span class="line">                &lt;input type=<span class="string">&quot;text&quot;</span> class=<span class="string">&quot;form-control&quot;</span> name=<span class="string">&quot;selectBookName&quot;</span> placeholder=<span class="string">&quot;请输入要查询的书籍&quot;</span>&gt;</span><br><span class="line">                &lt;span class=<span class="string">&quot;input-group-btn&quot;</span>&gt;</span><br><span class="line">                        &lt;button class=<span class="string">&quot;btn btn-success btn-search&quot;</span>&gt;搜索&lt;/button&gt;</span><br><span class="line">                    &lt;/span&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        &lt;/form&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;br&gt;</span><br><span class="line">    &lt;div class=<span class="string">&quot;row clearfix&quot;</span>&gt;</span><br><span class="line">        &lt;div class=<span class="string">&quot;col-md-12 column&quot;</span>&gt;</span><br><span class="line">            &lt;table class=<span class="string">&quot;table table-hover table-striped&quot;</span>&gt;</span><br><span class="line">                &lt;thead&gt;</span><br><span class="line">                &lt;th&gt;书籍编号&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;书籍名称&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;书籍数量&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;书籍描述&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;操作&lt;/th&gt;</span><br><span class="line">                &lt;/thead&gt;</span><br><span class="line">                &lt;tbody&gt;</span><br><span class="line">                &lt;c:forEach <span class="keyword">var</span>=<span class="string">&quot;book&quot;</span> items=<span class="string">&quot;$&#123;list&#125;&quot;</span>&gt;</span><br><span class="line">                    &lt;tr&gt;</span><br><span class="line">                        &lt;td&gt;$&#123;book.bookId&#125;&lt;/td&gt;</span><br><span class="line">                        &lt;td&gt;$&#123;book.bookName&#125;&lt;/td&gt;</span><br><span class="line">                        &lt;td&gt;$&#123;book.bookCounts&#125;&lt;/td&gt;</span><br><span class="line">                        &lt;td&gt;$&#123;book.detail&#125;&lt;/td&gt;</span><br><span class="line">                        &lt;td&gt;</span><br><span class="line">                            &lt;a href=<span class="string">&quot;$&#123;pageContext.request.contextPath&#125;/toUpdate?id=$&#123;book.bookId&#125;&quot;</span>&gt;修改&lt;/a&gt;</span><br><span class="line">                            &amp;nbsp; | &amp;nbsp;</span><br><span class="line">                            &lt;a href=<span class="string">&quot;$&#123;pageContext.request.contextPath&#125;/delBook?id=$&#123;book.bookId&#125;&quot;</span>&gt;删除&lt;/a&gt;</span><br><span class="line">                        &lt;/td&gt;</span><br><span class="line">                    &lt;/tr&gt;</span><br><span class="line">                &lt;/c:forEach&gt;</span><br><span class="line">                &lt;/tbody&gt;</span><br><span class="line">            &lt;/table&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;div class=<span class="string">&quot;row clearfix&quot;</span>&gt;</span><br><span class="line">        &lt;div class=<span class="string">&quot;col-md-12 column&quot;</span>&gt;</span><br><span class="line">            &lt;div class=<span class="string">&quot; text-right&quot;</span>&gt;</span><br><span class="line">                &lt;h3&gt;</span><br><span class="line">                    &lt;small&gt;$&#123;error&#125;&lt;/small&gt;</span><br><span class="line">                &lt;/h3&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/div&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure><p>添加书籍页面（WEB-INF / jsp / <code>addBook.jsp</code>）</p><figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ taglib prefix=<span class="string">&quot;c&quot;</span> uri=<span class="string">&quot;http://java.sun.com/jsp/jstl/core&quot;</span> %&gt;</span><br><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;title&gt;新增书籍&lt;/title&gt;</span><br><span class="line">    &lt;%--引入BootStrap--%&gt;</span><br><span class="line">    &lt;link rel=<span class="string">&quot;stylesheet&quot;</span> href=<span class="string">&quot;https://npm.elemecdn.com/bootstrap@3.3.7/dist/css/bootstrap.min.css&quot;</span></span><br><span class="line">          integrity=<span class="string">&quot;sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u&quot;</span> crossorigin=<span class="string">&quot;anonymous&quot;</span>&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line"></span><br><span class="line">&lt;div class=<span class="string">&quot;container&quot;</span>&gt;</span><br><span class="line">    &lt;div class=<span class="string">&quot;row clearfix&quot;</span>&gt;</span><br><span class="line">        &lt;div class=<span class="string">&quot;col-md-12 column&quot;</span>&gt;</span><br><span class="line">            &lt;div class=<span class="string">&quot;page-header text-center&quot;</span>&gt;</span><br><span class="line">                &lt;h1&gt;</span><br><span class="line">                    &lt;small&gt;新增书籍&lt;/small&gt;</span><br><span class="line">                &lt;/h1&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line"></span><br><span class="line">    &lt;form action=<span class="string">&quot;$&#123;pageContext.request.contextPath&#125;/addBook&quot;</span> method=<span class="string">&quot;post&quot;</span> class=<span class="string">&quot;form-inline text-center&quot;</span>&gt;</span><br><span class="line">        &lt;div class=<span class="string">&quot;form-group&quot;</span>&gt;</span><br><span class="line">            &lt;label&gt;书籍名称:&lt;/label&gt;</span><br><span class="line">            &lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;bookName&quot;</span> class=<span class="string">&quot;form-control&quot;</span> required&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line"></span><br><span class="line">        &lt;div class=<span class="string">&quot;form-group&quot;</span>&gt;</span><br><span class="line">            &lt;label&gt;书籍数量:&lt;/label&gt;</span><br><span class="line">            &lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;bookCounts&quot;</span> class=<span class="string">&quot;form-control&quot;</span> required&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line"></span><br><span class="line">        &lt;div class=<span class="string">&quot;form-group&quot;</span>&gt;</span><br><span class="line">            &lt;label&gt;书籍描述:&lt;/label&gt;</span><br><span class="line">            &lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;detail&quot;</span> class=<span class="string">&quot;form-control&quot;</span> required&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">        &amp;nbsp;</span><br><span class="line">        &lt;button type=<span class="string">&quot;submit&quot;</span> class=<span class="string">&quot;btn btn-info&quot;</span>&gt;点击添加&lt;/button&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">&lt;/div&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure><p>修改书籍页面（WEB-INF / jsp / <code>updateBook.jsp</code>）</p><figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ taglib prefix=<span class="string">&quot;c&quot;</span> uri=<span class="string">&quot;http://java.sun.com/jsp/jstl/core&quot;</span> %&gt;</span><br><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;title&gt;修改书籍&lt;/title&gt;</span><br><span class="line">    &lt;%--引入BootStrap--%&gt;</span><br><span class="line">    &lt;link rel=<span class="string">&quot;stylesheet&quot;</span> href=<span class="string">&quot;https://npm.elemecdn.com/bootstrap@3.3.7/dist/css/bootstrap.min.css&quot;</span></span><br><span class="line">          integrity=<span class="string">&quot;sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u&quot;</span> crossorigin=<span class="string">&quot;anonymous&quot;</span>&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line"></span><br><span class="line">&lt;div class=<span class="string">&quot;container&quot;</span>&gt;</span><br><span class="line"></span><br><span class="line">    &lt;div class=<span class="string">&quot;row clearfix&quot;</span>&gt;</span><br><span class="line">        &lt;div class=<span class="string">&quot;col-md-12 column&quot;</span>&gt;</span><br><span class="line">            &lt;div class=<span class="string">&quot;page-header text-center&quot;</span>&gt;</span><br><span class="line">                &lt;h1&gt;</span><br><span class="line">                    &lt;small&gt;修改书籍&lt;/small&gt;</span><br><span class="line">                &lt;/h1&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line"></span><br><span class="line">    &lt;form action=<span class="string">&quot;$&#123;pageContext.request.contextPath&#125;/updateBook&quot;</span> method=<span class="string">&quot;post&quot;</span> class=<span class="string">&quot;form-inline text-center&quot;</span>&gt;</span><br><span class="line">        &lt;%--隐藏域--%&gt;</span><br><span class="line">        &lt;input type=<span class="string">&quot;hidden&quot;</span> name=<span class="string">&quot;bookId&quot;</span> value=<span class="string">&quot;$&#123;toBook.bookId&#125;&quot;</span>&gt;</span><br><span class="line"></span><br><span class="line">        &lt;div class=<span class="string">&quot;form-group&quot;</span>&gt;</span><br><span class="line">            &lt;label&gt;书籍名称:&lt;/label&gt;</span><br><span class="line">            &lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;bookName&quot;</span> class=<span class="string">&quot;form-control&quot;</span> value=<span class="string">&quot;$&#123;toBook.bookName&#125;&quot;</span> required&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line"></span><br><span class="line">        &lt;div class=<span class="string">&quot;form-group&quot;</span>&gt;</span><br><span class="line">            &lt;label&gt;书籍数量:&lt;/label&gt;</span><br><span class="line">            &lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;bookCounts&quot;</span> class=<span class="string">&quot;form-control&quot;</span> value=<span class="string">&quot;$&#123;toBook.bookCounts&#125;&quot;</span></span><br><span class="line">                   onkeyup=<span class="string">&quot;this.value=this.value.replace(/\D/g,&#x27;&#x27;)&quot;</span></span><br><span class="line">                   onafterpaste=<span class="string">&quot;this.value=this.value.replace(/\D/g,&#x27;&#x27;)&quot;</span> required&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line"></span><br><span class="line">        &lt;div class=<span class="string">&quot;form-group&quot;</span>&gt;</span><br><span class="line">            &lt;label&gt;书籍描述:&lt;/label&gt;</span><br><span class="line">            &lt;input type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;detail&quot;</span> class=<span class="string">&quot;form-control&quot;</span> value=<span class="string">&quot;$&#123;toBook.detail&#125;&quot;</span> required&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line"></span><br><span class="line">        &lt;button type=<span class="string">&quot;submit&quot;</span> class=<span class="string">&quot;btn btn-default&quot;</span>&gt;点击修改&lt;/button&gt;</span><br><span class="line">    &lt;/form&gt;</span><br><span class="line">&lt;/div&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure><p>配置好 <code>Tomcat</code> 直接启动访问 <code>http://localhost:8080</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/ssm-config/image-20201222194238811.webp" alt="img"></p>]]></content>
    
    
    <summary type="html">虽然 ssm 整合教程都烂大街了，而我这篇文章也仅仅是我今天做为复习记录一下... 怎么说也踩到坑了(真的太久没配置了)，但是我不会告诉你的，总而言之 spring boot 真香</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="SSM" scheme="https://blog.imzjw.cn/tags/SSM/"/>
    
  </entry>
  
  <entry>
    <title>浅谈 Spring 声明式事务</title>
    <link href="https://blog.imzjw.cn/posts/spring-transaction/"/>
    <id>https://blog.imzjw.cn/posts/spring-transaction/</id>
    <published>2020-12-21T08:44:44.000Z</published>
    <updated>2020-12-21T08:44:44.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="事务"><a href="#事务" class="headerlink" title="事务"></a>事务</h2><ul><li><p>事务的四大特性（ACID）</p><ul><li><p>原子性：一个事务要么全部执行，要么不执行，也就是说一个事务不可能只执行了一半就停止了。</p><p>经典的例子：比如你从取款机取钱，这个事务可以分成两个步骤</p><p>1、插卡，2、出钱。不可能插了卡，而钱却没出来。这两步必须同时完成，要么就不完成。</p></li><li><p>一致性：事务的运行并不改变数据库中数据的一致性。</p></li><li><p>隔离性：数据库为每一个用户开启的事务，不能被其他事务的操作数据所干扰，多个并发事务之间要相互隔离。</p></li><li><p>持久性：事务执行成功以后，该事务对数据库所作的更改是持久的保存在数据库中</p></li></ul></li><li><p>事务在项目开发过程中，十分重要，涉及数据的一致性问题，不能马虎</p></li><li><p>确保完整性和一致性</p></li></ul><h2 id="Spring中的事务管理"><a href="#Spring中的事务管理" class="headerlink" title="Spring中的事务管理"></a>Spring中的事务管理</h2><ul><li><strong>编程式事务管理</strong><ul><li>将事务管理代码嵌到业务方法中来控制事务的提交和回滚</li><li>缺点：必须在每个事务操作业务逻辑中包含额外的事务管理代码</li></ul></li><li><strong>声明式事务管理</strong><ul><li>一般情况下比编程式事务好用。</li><li>将事务管理代码从业务方法中分离出来，以声明的方式来实现事务管理。</li><li>将事务管理作为横切关注点，通过<code>aop</code>方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。</li></ul></li></ul><h2 id="JDBC事务"><a href="#JDBC事务" class="headerlink" title="JDBC事务"></a>JDBC事务</h2><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 配置事务管理器 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;transactionManager&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 注入数据库连接池 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;dataSource&quot;</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure><p>配置好事务管理器后我们需要去配置事务的通知</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--结合AOP实现事务的织入--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--配置事务通知--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">tx:advice</span> <span class="attr">id</span>=<span class="string">&quot;txAdvice&quot;</span> <span class="attr">transaction-manager</span>=<span class="string">&quot;transactionManager&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--给那些方法配置事务--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--配置事务的传播特性:propagation(默认REQUIRED)--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tx:attributes</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;add&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;delete&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;update&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;query&quot;</span> <span class="attr">read-only</span>=<span class="string">&quot;true&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tx:attributes</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">tx:advice</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--配置事务切入--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">aop:config</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">aop:pointcut</span> <span class="attr">id</span>=<span class="string">&quot;txPointCut&quot;</span> <span class="attr">expression</span>=<span class="string">&quot;execution(* cn.imzjw.mapper.*.*(..))&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">aop:advisor</span> <span class="attr">advice-ref</span>=<span class="string">&quot;txAdvice&quot;</span> <span class="attr">pointcut-ref</span>=<span class="string">&quot;txPointCut&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">aop:config</span>&gt;</span></span><br></pre></td></tr></table></figure><p>为什么需要事务？</p><ul><li>如果不配置事务，可能存在数据提交不一致的情况下</li><li>如果我们不在<code>Spring</code>中去配置声明式事务，那么就需要在代码中手动配置事务，但我还是喜欢<code>声明式事务</code></li></ul>]]></content>
    
    
    <summary type="html">事务的四大特性（ACID）原子性：一个事务要么全部执行，要么不执行，也就是说一个事务不可能只执行了一半就停止了。一致性：事务的运行并不改变数据库中数据的一致性</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring" scheme="https://blog.imzjw.cn/tags/Spring/"/>
    
  </entry>
  
  <entry>
    <title>本地电脑如何配置多个 GitHub 账号</title>
    <link href="https://blog.imzjw.cn/posts/9b6773cf/"/>
    <id>https://blog.imzjw.cn/posts/9b6773cf/</id>
    <published>2020-12-20T04:43:20.000Z</published>
    <updated>2020-12-20T04:43:20.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h2><p>当有多个 git 账号时，就比如</p><p>主账户：用于个人项目开发</p><p>子账户：比如拿来存存 <code>img</code>，<code>StaticFile </code>然后用 <code>jsd</code> 加速 等..</p><p>又或者 <code>gitlab</code></p><h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>多个 Git 账号，但是邮箱不同，且只有一个 <code>id_rsa_pub</code> 公钥，无法绑定多个github账户，这样就会导致有一个账户用不了，当然你可以选择Https，但这将会是繁琐的过程</p><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><p>生成多个不同的公私密钥对，从 <code>config</code> 文件管理它们</p><ol><li><p>查看已有的 <code>密钥</code>，输入以下命令</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">ls</span> ~/.ssh/</span><br></pre></td></tr></table></figure><p>可以看到<code>id_rsa</code>和<code>id_rsa_pub</code>，其中 <code>id_rsa</code> 是私钥  <code>id_rsa_pub</code> 是公钥</p></li><li><p>生成新的公钥，并命名为 <code>id_rsa_pub2</code>（随便命名，也可以 <code>id_rsa_pub_github用户名</code>，这样就好区分开）输入以下命令</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -t rsa -f ~/.ssh/id_rsa_2 -C <span class="string">&quot;yourmail@xxx.com&quot;</span></span><br></pre></td></tr></table></figure><p>按三下回车之后就可以发现 <code>.ssh</code> 目录下有我们刚刚生成的 <code>id_rsa_2.pub</code>，复制 <code>id_rsa_2.pub</code> 内容到  github 子账户进行绑定</p></li><li><p>在 <code>.ssh</code> 文件夹下新建 <code>config</code> 文件并编辑</p><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 默认账户                                                                       </span></span><br><span class="line"><span class="attr">Host</span> <span class="string">github.com</span></span><br><span class="line"><span class="attr">HostName</span> <span class="string">github.com</span></span><br><span class="line"><span class="attr">User</span> <span class="string">git</span></span><br><span class="line"><span class="attr">IdentityFile</span> <span class="string">~/.ssh/id_rsa</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># 子账户1                                                                           </span></span><br><span class="line"><span class="attr">Host</span> <span class="string">xiaojia.github.com# Host实际映射到HostName，但密钥文件不同，可自定义</span></span><br><span class="line"><span class="attr">HostName</span> <span class="string">github.com</span></span><br><span class="line"><span class="attr">User</span> <span class="string">git</span></span><br><span class="line"><span class="attr">IdentityFile</span> <span class="string">~/.ssh/id_rsa2# &lt;-- 注意这里，修改成你自己自定义的名字</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># 子账户2</span></span><br><span class="line"><span class="attr">...</span></span><br></pre></td></tr></table></figure></li><li><p>测试 <code>ssh</code>连接是否成功，输入以下命令</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ssh -T git@github.com</span><br><span class="line">ssh -T git@xiaojia.github.com</span><br></pre></td></tr></table></figure><p>Hi xiaojia! You’ve successfully authenticated, but GitHub does not provide shell access.</p><p>出现以上这句话，表示连接成功</p></li><li><p>接着要注意的地方，也就是 clone 子账户时要注意，原本  clone  的方式是这样的</p><p>git clone git@<code>github.com</code>:xxx/xxx.git</p><p>现在改为  git clone git@<code>xiaojia.github.com</code>:xxx/xxx.git，对应你config文件里的Host</p><p>那么问题又来了，git  的用户名和邮箱我配置了全局咋办</p><p>这好办，直接取消全局，然后进入项目里面进行单独设置</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">取消用户名和邮箱全局配置</span></span><br><span class="line">git config --global --unset user.name</span><br><span class="line">git config --global --unset user.email</span><br></pre></td></tr></table></figure></li><li><p>cd 项目</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">单独配置用户名和邮箱</span></span><br><span class="line">git config user.name &quot;xxx&quot;</span><br><span class="line">git config user.email &quot;xxx@xxx.com&quot;</span><br></pre></td></tr></table></figure></li><li><p>最后直接 push</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push -u origin master</span><br></pre></td></tr></table></figure><p>大功告成😁</p></li></ol><h2 id="存在问题"><a href="#存在问题" class="headerlink" title="存在问题"></a>存在问题</h2><p>如果已存在的项目发现 push 不上去，那么执行如下命令，如没问题，请忽略！</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git remote rm origin</span><br><span class="line">git remote add origin git@xiaojia.github.com:xxx</span><br></pre></td></tr></table></figure><p>其实也就是重新关联远程仓库</p>]]></content>
    
    
    <summary type="html">当有多个 git 账号时，就比如主账户：用于个人项目开发,子账户：比如拿来存存img，StaticFile然后用jsd加速等，多个 Git 账号，但是邮箱不同，且只有一个id_rsa_pub公钥，无法绑定多个github账户，这样就会导致有一个账户用不了</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="GitHub" scheme="https://blog.imzjw.cn/tags/GitHub/"/>
    
  </entry>
  
  <entry>
    <title>使用宝塔面板安装Typecho博客</title>
    <link href="https://blog.imzjw.cn/posts/baota-typecho/"/>
    <id>https://blog.imzjw.cn/posts/baota-typecho/</id>
    <published>2020-12-17T13:16:56.000Z</published>
    <updated>2020-12-17T13:16:56.000Z</updated>
    
    <content type="html"><![CDATA[<p>今天不知道抽啥风，安装了个动态的博客（Typecho），大概是好奇后台的 blog 到底是什么样</p><p>网上的教程也有很多，而我也只是记录下今天的安装过程 仅此而已</p><h2 id="前期准备"><a href="#前期准备" class="headerlink" title="前期准备"></a>前期准备</h2><p>首先你得要有一台服务器</p><p>如果你符合学生机条件的话推荐学生机</p><p>阿里学生机地址：<a href="https://developer.aliyun.com/plan/grow-up">https://developer.aliyun.com…</a>  腾讯学生机地址：<a href="https://cloud.tencent.com/act/campus?from=11821">https://cloud.tencent.com…</a></p><p>华为学生机：<a href="https://developer.huaweicloud.com/campus?productType=KC1_1&timeType=3&regionType=1&domainItemData=">https://developer.huaweicloud.com…</a> 等</p><p>SSH 工具推荐 <a href="https://www.hostbuf.com/t/988.html">FinalShell</a>，当然你也可以用其它的，比如 XShell 都可以，随你</p><h2 id="正式开始"><a href="#正式开始" class="headerlink" title="正式开始"></a>正式开始</h2><ol><li><p>使用 <code>FinalSheel</code> 连接你的服务器</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/baota-typecho/20201217214802.webp" alt="img"></p></li><li><p>安装宝塔 Linux 面板，官网安装教程：<a href="https://www.bt.cn/bbs/thread-19376-1-1.html">https://www.bt.cn…</a> </p><p>输入以下命令安装</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install -y wget &amp;&amp; wget -O install.sh http://download.bt.cn/install/install_6.0.sh &amp;&amp; sh install.sh</span><br></pre></td></tr></table></figure><p>安装过程有个提示，输入 <code>y</code> 即可，安装完成后记录宝塔面板的登录账号和密码，然后选择 <code>LNMP</code>，极速安装</p></li><li><p><code>LNMP</code> 那些坏境安装完成后，点击 <kbd>网站</kbd> –&gt; <kbd>添加站点</kbd></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/baota-typecho/image-20201217220523242.webp" alt="img"></p></li><li><p>填写你的域名，创建数据库，必须 UTF-8 字符集</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/baota-typecho/image-20201217220939509.webp" alt="img"></p></li><li><p>现在就已经完成了 80% 了，简单吧，接着到 <code>Typecho</code> 官网下载程序，这里提供官网下载直链，免得你又跑去 <code>Typecho</code> 官网，<a href="https://typecho.org/downloads/1.1-17.10.30-release.tar.gz">官网下载直链</a></p></li><li><p>我们在网站那里点击网站目录并且把那些默认文件全删了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/baota-typecho/image-20201217221542954.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/bt-deploy-vue/image-20201217221739646.webp" alt="img"></p></li><li><p>上传 <code>Typecho</code> 程序，然后解压</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/baota-typecho/image-20201217221914349.webp" alt="img"></p></li><li><p>上传完成之后，在浏览器输入自己的域名进行数据库配置，填写相关信息，数据库密码可以在宝塔面板的数据库进行查看</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/baota-typecho/image-20201217222421136.webp" alt="img"></p></li><li><p>大功告成</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/baota-typecho/20201217222541.webp" alt="img"></p></li></ol><h2 id="主题"><a href="#主题" class="headerlink" title="主题"></a>主题</h2><p><a href="https://typecho.me/">typecho.me</a>， 这里提供了 <code>Typecho</code> 主题模板演示及下载服务</p><p>主题安装的话，请把主题上传到 <kbd>usr</kbd> 下的 <kbd>themes</kbd></p><p>最后在 <code>Typecho</code> 的后台，外观，启用就好了</p><h2 id="其它问题"><a href="#其它问题" class="headerlink" title="其它问题"></a>其它问题</h2><p>关于永久链接设置里的 <strong>是否使用地址重写功能</strong></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/baota-typecho/image-20201217225639267.webp" alt="img"></p><p>这个在 <code>nginx</code> 配置文件里加上如下代码即可</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">if</span> (!-e <span class="variable">$request_filename</span>) &#123;</span><br><span class="line">    <span class="attribute">rewrite</span><span class="regexp"> ^(.*)$</span> /index.php<span class="variable">$1</span> <span class="literal">last</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后还是提示 <strong>重写功能检测失败, 请检查你的服务器设置</strong>，那么请勾选那个复选框（如果你仍然想启用此功能，请勾选这里）</p><p>goodbye！！</p>]]></content>
    
    
    <summary type="html">今天不知道抽啥风，安装了个动态的博客(Typecho), 大概是好奇后台的blog到底是什么样，网上的教程也有很多，而我也只是记录下今天的安装过程 仅此而已</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="Typecho" scheme="https://blog.imzjw.cn/tags/Typecho/"/>
    
  </entry>
  
  <entry>
    <title>Maven 仓库和坐标详解</title>
    <link href="https://blog.imzjw.cn/posts/df639dfc/"/>
    <id>https://blog.imzjw.cn/posts/df639dfc/</id>
    <published>2020-12-14T09:20:28.000Z</published>
    <updated>2020-12-14T09:20:28.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Maven-的仓库"><a href="#Maven-的仓库" class="headerlink" title="Maven 的仓库"></a>Maven 的仓库</h2><ul><li>本地仓库<ul><li>相当于缓存，工程第一次会从远程仓库（互联网）去下载 jar 包，将 jar 包存在本地仓库（在程序员的电脑上）。第二次不需要从远程仓库去下载。先从本地仓库找，如果找不到才会去远程仓库找</li></ul></li><li>中央仓库<ul><li>仓库中 jar 由专业团队（maven 团队）统一维护。中央仓库的地址：<a href="https://repo1.maven.org/maven2/">https://repo1.maven.org/maven2/</a></li></ul></li><li>远程仓库<ul><li>在公司内部架设一台私服，其它公司架设一台仓库，对外公开。</li></ul></li></ul><h3 id="下载-jar-包缓慢的问题"><a href="#下载-jar-包缓慢的问题" class="headerlink" title="下载 jar 包缓慢的问题"></a>下载 jar 包缓慢的问题</h3><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df639dfc/20201214172916.webp" alt="img"></p><p>一般来说，不管是我们之前手动去下载 <code>jar</code> 包，或者后续在Maven中央仓库下载  <code>jar</code> 包，都可能因为一些下载地址在国外，导致下载缓慢的情况，这就影响到我们构建项目的效率了。</p><p>那该怎么解决呢？？</p><div class="hide-block"><button type="button" class="hide-button" style="">答案    </button><div class="hide-content"><p>可以使用缓存。</p></div></div><div class="note success flat"><p>使用 本地仓库 作为 本地 jar 包下载的缓存</p></div><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df639dfc/20201214173210.webp" alt="img"></p><p>那么在第一次下载的 jar 包的过程还是比较缓慢的，由于第一次下载完毕之后，就会将 jar 包保存在本地仓库。那么第二次开始，再次下载使用该 jar 包的话，效率就会提升。</p><p>但是，本地仓库并没有解决第一次从 maven中央仓库 下载 jar 包缓慢的问题。又该怎么解决呢？</p><div class="note success flat"><p>可以配置阿里云仓库，提供国内开发人员下载 jar 包</p></div><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df639dfc/20201214173506.webp" alt="img"></p><p>为了解决第一次从国外下载 jar 包缓慢的问题，阿里云将中央仓库的 jar 包复制下载。并在国内提供远程仓库服务，提供国内开发者下载，从而解决第一次下载效率低的问题。</p><ol><li><p>打开 <code>apache-maven-版本号\conf\settings.xml</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df639dfc/20201214181014.webp" alt="img"></p></li><li><p>找到 <code>&lt;mirrors&gt;&lt;/mirrors&gt;</code> 标签，在其中配置阿里云镜像</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">mirrors</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mirror</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">id</span>&gt;</span>alimaven<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">mirrorOf</span>&gt;</span>central<span class="tag">&lt;/<span class="name">mirrorOf</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">name</span>&gt;</span>aliyun maven<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">url</span>&gt;</span>http://maven.aliyun.com/nexus/content/repositories/central/<span class="tag">&lt;/<span class="name">url</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">mirror</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">mirrors</span>&gt;</span></span><br></pre></td></tr></table></figure><p>使用此 maven 的配置作为版本控制，都会从阿里云的仓库中下载代码，速度贼快</p><p>当然，这个远程仓库我们也可以在自己的公司内部中搭建的哦！</p></li></ol><h2 id="Maven-的坐标"><a href="#Maven-的坐标" class="headerlink" title="Maven 的坐标"></a>Maven 的坐标</h2><p>Maven 的一个核心的作用就是管理项目的依赖，引入我们所需的各种 jar 包等。为了能自动化的解析任何一个 Java 构件，Maven 必须将这些 Jar 包或者其他资源进行唯一标识，这是管理项目的依赖的基础，也就是我们要说的坐标。包括我们自己开发的项目，也是要通过坐标进行唯一标识的，这样才能才其它项目中进行依赖引用。坐标的定义元素如下</p><div class='checkbox green checked'><input type="checkbox" checked="checked"/>            <p>groupId 项目组织唯一的标识符，实际对应 JAVA 的包的结构 (一般写公司的组织名称 com.alibaba )</p>            </div><div class='checkbox green checked'><input type="checkbox" checked="checked"/>            <p>artifactId 项目的名称</p>            </div><div class='checkbox green checked'><input type="checkbox" checked="checked"/>            <p>version 定义项目的当前版本</p>            </div><h3 id="访问Maven的中央仓库"><a href="#访问Maven的中央仓库" class="headerlink" title="访问Maven的中央仓库"></a>访问Maven的中央仓库</h3><p>访问 <a href="https://repo1.maven.org/maven2/">Maven中央仓库</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df639dfc/20201214174248.webp" alt="img"></p><p>可以看到包含了非常多的 jar 包。</p><p>并且从 <code>com.alibaba</code> 的路径下可以找到很多 阿里巴巴 的项目。而这个 <code>com.alibaba</code> 就是公司的组织名称。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df639dfc/20201214174455.webp" alt="img"></p><p>通过 组织名 + 项目名 + 版本号，就可以定位需要的 jar 包</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df639dfc/20201214174934.webp" alt="img"></p><p>在项目中配置 jar 包的引入，只需要在 pom.xml 中配置 jar 包的 组织名 + 项目名 + 版本号 就行了。</p><p>例如：要引入druid，只需要在pom.xml配置文件中配置引入druid的坐标就好啦💋</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependecies</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--druid连接池--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>druid<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span>    </span><br><span class="line">  <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.2.4<span class="tag">&lt;/<span class="name">version</span>&gt;</span>  </span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependecies</span>&gt;</span></span><br></pre></td></tr></table></figure><p>但是这里有个问题，我们一般都 <del>记不住</del> (不记) 这些 jar 包的 组织名 + 项目名 + 版本号 的信息。</p><p>所以我们就可以用 Google 搜索引擎来搜索 maven中央仓库，然后在 maven 中央仓库来搜索 jar 包的坐标信息</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df639dfc/20201214175422.webp" alt="img"></p><p>然后我们就可以在 maven 中央仓库搜索我们想要的 jar 包坐标啦</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df639dfc/20201214175619.webp" alt="img"></p><p>点击进入项目名</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df639dfc/20201214175656.webp" alt="img"></p><p>选择需要的版本号</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df639dfc/20201214175837.webp" alt="img"></p><p><kbd>Ctrl</kbd> + <kbd>C</kbd> maven 的坐标信息</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df639dfc/20201214180026.webp" alt="img"></p><p>然后就可以在 pom.xml 文件中 <kbd>Ctrl</kbd> + <kbd>V</kbd> 了</p>]]></content>
    
    
    <summary type="html">本地仓库：相当于缓存，工程第一次会从远程仓库（互联网）去下载 jar 包，将 jar 包存在本地仓库（在程序员的电脑上）。第二次不需要从远程仓库去下载。先从本地仓库找</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Maven" scheme="https://blog.imzjw.cn/tags/Maven/"/>
    
  </entry>
  
  <entry>
    <title>介绍几个国外的技术论坛社区</title>
    <link href="https://blog.imzjw.cn/posts/foreign-technical-community/"/>
    <id>https://blog.imzjw.cn/posts/foreign-technical-community/</id>
    <published>2020-12-05T13:56:01.000Z</published>
    <updated>2020-12-05T13:56:01.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="stackoverflow"><a href="#stackoverflow" class="headerlink" title="stackoverflow"></a>stackoverflow</h2><p>这第一个肯定就是  <code> stackoverflow</code>  一个问答类的技术社区，和国内的知乎比较相似，但和知乎不同的是 <code>stackoverflow</code> 更垂直于技术，不像知乎内容比较杂叭</p><p>地址：<a href="https://stackoverflow.com/">stackoverflow</a></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/foreign-technical-community/foreign20201205221029.webp" alt="stackoverflow"><h2 id="simpleprogrammer"><a href="#simpleprogrammer" class="headerlink" title="simpleprogrammer"></a>simpleprogrammer</h2><p>看这名字就知道了，<code>简单的程序员</code></p><p>主要还是讲职场的一些东西</p><p>地址：<a href="https://simpleprogrammer.com/">simpleprogrammer</a></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/foreign-technical-community/foreign20201205221455.webp" alt="simpleprogrammer"><h2 id="sitepoint"><a href="#sitepoint" class="headerlink" title="sitepoint"></a>sitepoint</h2><p>一个偏向前端、移动端的技术网站，有一些高质量的前端方面的文章、电子书。</p><p>地址：<a href="https://www.sitepoint.com/web/">sitepoint</a></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/foreign-technical-community/foreign20201205221816.webp" alt="sitepoint"><h2 id="dev"><a href="#dev" class="headerlink" title="dev"></a>dev</h2><p>dev 社区和国内的掘金很相似，技术分类也蛮多</p><p>地址：<a href="https://dev.to/t/java">dev</a></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/foreign-technical-community/foreign20201205222426.webp" alt="dev"><h2 id="Google-Developers"><a href="#Google-Developers" class="headerlink" title="Google Developers"></a>Google Developers</h2><p><code>Google</code> 开发者社区</p><p>地址：<a href="https://developers.google.com/">Google Developers</a></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/foreign-technical-community/foreign20201205223235.webp" alt="Google Developers"><h2 id="daniweb"><a href="#daniweb" class="headerlink" title="daniweb"></a>daniweb</h2><p>地址：<a href="https://www.daniweb.com/">daniweb</a></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/foreign-technical-community/foreign20201205223657.webp" alt="daniweb"><h2 id="Dzone"><a href="#Dzone" class="headerlink" title="Dzone"></a>Dzone</h2><p>Dzone 是一个技术涵盖比较全面的网站</p><p>地址：<a href="https://dzone.com/">Dzone</a></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/foreign-technical-community/foreign20201205224019.webp" alt="Dzone"><h2 id="dreamincode"><a href="#dreamincode" class="headerlink" title="dreamincode"></a>dreamincode</h2><p>就是有广告😊</p><p>地址：<a href="https://www.dreamincode.net/">dreamincode</a></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/foreign-technical-community/foreign20201205224252.webp" alt="dreamincode"><h2 id="bytes"><a href="#bytes" class="headerlink" title="bytes"></a>bytes</h2><p>地址：<a href="https://bytes.com/">bytes</a></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/foreign-technical-community/foreign20201205224426.webp" alt="bytes"><p>其实除了这些我感觉 Facebook 也算一个小社区，因为那里有一个 <code>小组</code>，和外国人交流其实也还别有一番风味</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/foreign-technical-community/foreign20201205224723.webp" alt="Facebook">]]></content>
    
    
    <summary type="html">这第一个肯定就是stackoverflow，一个问答类的技术社区，和国内的知乎比较相似，但和知乎不同的是stackoverflow更垂直于技术，不像知乎内容比较杂</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="论坛" scheme="https://blog.imzjw.cn/tags/%E8%AE%BA%E5%9D%9B/"/>
    
  </entry>
  
  <entry>
    <title>Java复习-基础</title>
    <link href="https://blog.imzjw.cn/posts/java-basics/"/>
    <id>https://blog.imzjw.cn/posts/java-basics/</id>
    <published>2020-12-03T12:44:52.000Z</published>
    <updated>2020-12-03T12:44:52.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="数据类型"><a href="#数据类型" class="headerlink" title="数据类型"></a>数据类型</h2><h3 id="基本类型"><a href="#基本类型" class="headerlink" title="基本类型"></a>基本类型</h3><p>Java提供了八种基本类型。六种数字类型（四个整数型，两个浮点型），一种字符类型，还有一种布尔型。</p><ul><li>byte/8</li><li>char/16</li><li>short/16</li><li>int/32</li><li>float/32</li><li>long/64</li><li>double/64</li><li>boolean/~</li></ul><p><code>boolean</code> 只有两个值：true、false，可以使用 1 bit 来存储，但是具体大小没有明确规定。JVM 会在编译时期将 boolean 类型的数据转换为 int，使用 1 来表示 true，0 表示 false。JVM 支持 boolean 数组，但是是通过读写 byte 数组来实现的。</p><p><strong>参考：</strong><a href="https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html">Primitive Data Types</a>、<a href="https://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf">The Java® Virtual Machine Specification</a></p><h3 id="包装类型"><a href="#包装类型" class="headerlink" title="包装类型"></a>包装类型</h3><p>基本类型都有对应的包装类型，基本类型与其对应的包装类型之间的赋值使用自动<code>装箱</code>与<code>拆箱</code>完成。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">Integer</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">2</span>;     <span class="comment">// 装箱 调用了 Integer.valueOf(2)</span></span><br><span class="line"><span class="type">int</span> <span class="variable">y</span> <span class="operator">=</span> x;         <span class="comment">// 拆箱 调用了 X.intValue()</span></span><br></pre></td></tr></table></figure><p><strong>参考：</strong><a href="https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html">Autoboxing and Unboxing</a></p><h3 id="缓存池"><a href="#缓存池" class="headerlink" title="缓存池"></a>缓存池</h3><p><code>new</code>Integer(123) 与 Integer.valueOf(123) 的区别在于：</p><ul><li><code>new</code> Integer(123) 每次都会新建一个对象；</li><li>Integer.valueOf(123) 会使用缓存池中的对象，多次调用会取得同一个对象的引用。</li></ul><p>valueOf() 方法的实现比较简单，就是先判断值是否在缓存池中，如果在的话就直接返回缓存池的内容。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> Integer <span class="title function_">valueOf</span><span class="params">(<span class="type">int</span> i)</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (i &gt;= IntegerCache.low &amp;&amp; i &lt;= IntegerCache.high)</span><br><span class="line">        <span class="keyword">return</span> IntegerCache.cache[i + (-IntegerCache.low)];</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Integer</span>(i);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在 Java 8 中，Integer 缓存池的大小默认为 -128~127。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">low</span> <span class="operator">=</span> -<span class="number">128</span>;</span><br><span class="line"><span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> high;</span><br><span class="line"><span class="keyword">static</span> <span class="keyword">final</span> Integer cache[];</span><br><span class="line"></span><br><span class="line"><span class="keyword">static</span> &#123;</span><br><span class="line">    <span class="comment">// high value may be configured by property</span></span><br><span class="line">    <span class="type">int</span> <span class="variable">h</span> <span class="operator">=</span> <span class="number">127</span>;</span><br><span class="line">    <span class="type">String</span> <span class="variable">integerCacheHighPropValue</span> <span class="operator">=</span></span><br><span class="line">        sun.misc.VM.getSavedProperty(<span class="string">&quot;java.lang.Integer.IntegerCache.high&quot;</span>);</span><br><span class="line">    <span class="keyword">if</span> (integerCacheHighPropValue != <span class="literal">null</span>) &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> parseInt(integerCacheHighPropValue);</span><br><span class="line">            i = Math.max(i, <span class="number">127</span>);</span><br><span class="line">            <span class="comment">// Maximum array size is Integer.MAX_VALUE</span></span><br><span class="line">            h = Math.min(i, Integer.MAX_VALUE - (-low) -<span class="number">1</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span>( NumberFormatException nfe) &#123;</span><br><span class="line">            <span class="comment">// If the property cannot be parsed into an int, ignore it.</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    high = h;</span><br><span class="line"></span><br><span class="line">    cache = <span class="keyword">new</span> <span class="title class_">Integer</span>[(high - low) + <span class="number">1</span>];</span><br><span class="line">    <span class="type">int</span> <span class="variable">j</span> <span class="operator">=</span> low;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">k</span> <span class="operator">=</span> <span class="number">0</span>; k &lt; cache.length; k++)</span><br><span class="line">        cache[k] = <span class="keyword">new</span> <span class="title class_">Integer</span>(j++);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// range [-128, 127] must be interned (JLS7 5.1.7)</span></span><br><span class="line">    <span class="keyword">assert</span> IntegerCache.high &gt;= <span class="number">127</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译器会在自动装箱过程调用 valueOf() 方法，因此多个值相同且值在缓存池范围内的 Integer 实例使用自动装箱来创建，那么就会引用相同的对象。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">Integer</span> <span class="variable">m</span> <span class="operator">=</span> <span class="number">123</span>;</span><br><span class="line"><span class="type">Integer</span> <span class="variable">n</span> <span class="operator">=</span> <span class="number">123</span>;</span><br><span class="line">System.out.println(m == n); <span class="comment">// true</span></span><br></pre></td></tr></table></figure><p>基本类型对应的缓冲池如下：</p><ul><li>布尔值 true 和 false </li><li>所有字节值</li><li>介于-128和127之间的短值</li><li>int值介于-128和127之间</li><li>字符，范围从 \u0000 到 \u007F</li></ul><p>参考：<a href="https://stackoverflow.com/questions/9030817/differences-between-new-integer123-integer-valueof123-and-just-123">StackOverflow : Differences between new Integer(123), Integer.valueOf(123) and just 123 </a></p><h2 id="String"><a href="#String" class="headerlink" title="String"></a>String</h2><h3 id="概览"><a href="#概览" class="headerlink" title="概览"></a>概览</h3><p>String 被声明为 final，因此它不可被继承。( Integer 等包装类也不能被继承 ）</p><p>在 Java 8 中，String 内部使用 char 数组存储数据。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">class</span> <span class="title class_">String</span></span><br><span class="line">    <span class="keyword">implements</span> <span class="title class_">java</span>.io.Serializable, Comparable&lt;String&gt;, CharSequence &#123;</span><br><span class="line">    <span class="comment">// The value is used for character storage.</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="type">char</span> value[];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在 Java 9 之后，String 类的实现改用 byte 数组存储字符串，同时使用 <code>coder</code> 来标识使用了哪种编码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">class</span> <span class="title class_">String</span></span><br><span class="line">    <span class="keyword">implements</span> <span class="title class_">java</span>.io.Serializable, Comparable&lt;String&gt;, CharSequence &#123;</span><br><span class="line">    <span class="comment">/** The value is used for character storage. */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="type">byte</span>[] value;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** The identifier of the encoding used to encode the bytes in &#123;<span class="doctag">@code</span> value&#125;. */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="type">byte</span> coder;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>value 数组被声明为 final，这意味着 value 数组初始化之后就不能再引用其它数组。并且 String 内部没有改变 value 数组的方法，因此可以保证 String 不可变。</p><h3 id="不可变的好处"><a href="#不可变的好处" class="headerlink" title="不可变的好处"></a>不可变的好处</h3><ol><li><p><strong>可以缓存 hash 值</strong></p><p>因为 String 的 hash 值经常被使用，例如 String 用做 HashMap 的 key。不可变的特性可以使得 hash 值也不可变，因此只需要进行一次计算。</p></li><li><p><strong>String Pool 的需要</strong></p><p>如果一个 String 对象已经被创建过了，那么就会从 String Pool 中取得引用。只有 String 是不可变的，才可能使用 String Pool。</p></li><li><p><strong>安全性</strong></p><p>String 经常作为参数，String 不可变性可以保证参数不可变。例如在作为网络连接参数的情况下如果 String 是可变的，那么在网络连接过程中，String 被改变，改变 String 的那一方以为现在连接的是其它主机，而实际情况却不一定是。</p></li><li><p><strong>线程安全</strong></p><p>String 不可变性天生具备线程安全，可以在多个线程中安全地使用。</p></li></ol><p><strong>参考</strong>：<a href="https://www.programcreek.com/2013/04/why-string-is-immutable-in-java/">Program Creek : Why String is immutable in Java?</a></p><h3 id="String-StringBuffer-and-StringBuilder"><a href="#String-StringBuffer-and-StringBuilder" class="headerlink" title="String, StringBuffer and StringBuilder"></a>String, StringBuffer and StringBuilder</h3><ol><li><p><strong>可变性</strong></p><ul><li>String 不可变</li><li>StringBuffer 和 StringBuilder 可变</li></ul></li><li><p><strong>线程安全</strong></p><ul><li>String 不可变，因此是线程安全的</li><li>StringBuilder 不是线程安全的</li><li>StringBuffer 是线程安全的，内部使用 synchronized 进行同步</li></ul></li></ol><p><strong>参考：</strong><a href="https://stackoverflow.com/questions/2971315/string-stringbuffer-and-stringbuilder">StackOverflow : String, StringBuffer, and StringBuilder</a></p><h3 id="String-Pool"><a href="#String-Pool" class="headerlink" title="String Pool"></a>String Pool</h3><p>字符串常量池（String Pool）保存着所有字符串字面量（literal strings），这些字面量在编译时期就确定。不仅如此，还可以使用 String 的 intern() 方法在运行过程将字符串添加到 String Pool 中。</p><p>当一个字符串调用 intern() 方法时，如果 String Pool 中已经存在一个字符串和该字符串值相等（使用 equals() 方法进行确定），那么就会返回 String Pool 中字符串的引用；否则，就会在 String Pool 中添加一个新的字符串，并返回这个新字符串的引用。</p><p>下面示例中，s1 和 s2 采用 new String() 的方式新建了两个不同字符串，而 s3 和 s4 是通过 s1.intern() 和 s2.intern() 方法取得同一个字符串引用。intern() 首先把 “aaa” 放到 String Pool 中，然后返回这个字符串引用，因此 s3 和 s4 引用的是同一个字符串。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">s1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(<span class="string">&quot;aaa&quot;</span>);</span><br><span class="line"><span class="type">String</span> <span class="variable">s2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(<span class="string">&quot;aaa&quot;</span>);</span><br><span class="line">System.out.println(s1 == s2);  <span class="comment">// false</span></span><br><span class="line"><span class="type">String</span> <span class="variable">s3</span> <span class="operator">=</span> s1.intern();</span><br><span class="line"><span class="type">String</span> <span class="variable">s4</span> <span class="operator">=</span> s2.intern();</span><br><span class="line">System.out.println(s3 == s4);  <span class="comment">// true</span></span><br></pre></td></tr></table></figure><p>如果是采用 “bbb” 这种字面量的形式创建字符串，会自动地将字符串放入 String Pool 中。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">s5</span> <span class="operator">=</span> <span class="string">&quot;bbb&quot;</span>;</span><br><span class="line"><span class="type">String</span> <span class="variable">s6</span> <span class="operator">=</span> <span class="string">&quot;bbb&quot;</span>;</span><br><span class="line">System.out.println(s5 == s6);  <span class="comment">// true</span></span><br></pre></td></tr></table></figure><p>在 Java 7 之前，String Pool 被放在运行时常量池中，它属于永久代。而在 Java 7，String Pool 被移到堆中。这是因为永久代的空间有限，在大量使用字符串的场景下会导致 <code>OutOfMemoryError</code> 错误。</p><p><strong>参考：</strong><a href="https://stackoverflow.com/questions/10578984/what-is-string-interning">StackOverflow : What is String interning?</a>、<a href="https://tech.meituan.com/in_depth_understanding_string_intern.html">深入解析 String#intern</a></p><h3 id="new-String-“abc”"><a href="#new-String-“abc”" class="headerlink" title="new String(“abc”)"></a>new String(“abc”)</h3><p>使用这种方式一共会创建两个字符串对象（前提是 String Pool 中还没有 “abc” 字符串对象）。</p><ul><li>“abc” 属于字符串字面量，因此编译时期会在 String Pool 中创建一个字符串对象，指向这个 “abc” 字符串字面量；</li><li>而使用 new 的方式会在堆中创建一个字符串对象。</li></ul><p>创建一个测试类，其 main 方法中使用这种方式来创建字符串对象。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">NewStringTest</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">s</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(<span class="string">&quot;abc&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>使用 javap -verbose 进行反编译，得到以下内容：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ...</span></span><br><span class="line">Constant pool:</span><br><span class="line"><span class="comment">// ...</span></span><br><span class="line">   #<span class="number">2</span> = Class              #<span class="number">18</span>            <span class="comment">// java/lang/String</span></span><br><span class="line">   #<span class="number">3</span> = String             #<span class="number">19</span>            <span class="comment">// abc</span></span><br><span class="line"><span class="comment">// ...</span></span><br><span class="line">  #<span class="number">18</span> = Utf8               java/lang/String</span><br><span class="line">  #<span class="number">19</span> = Utf8               abc</span><br><span class="line"><span class="comment">// ...</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(java.lang.String[])</span>;</span><br><span class="line">    descriptor: ([Ljava/lang/String;)V</span><br><span class="line">    flags: ACC_PUBLIC, ACC_STATIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">3</span>, locals=<span class="number">2</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: <span class="keyword">new</span>           #<span class="number">2</span>              <span class="comment">// class java/lang/String</span></span><br><span class="line">         <span class="number">3</span>: dup</span><br><span class="line">         <span class="number">4</span>: ldc           #<span class="number">3</span>              <span class="comment">// String abc</span></span><br><span class="line">         <span class="number">6</span>: invokespecial #<span class="number">4</span>              <span class="comment">// Method java/lang/String.&quot;&lt;init&gt;&quot;:(Ljava/lang/String;)V</span></span><br><span class="line">         <span class="number">9</span>: astore_1</span><br><span class="line"><span class="comment">// ...</span></span><br></pre></td></tr></table></figure><p>在 Constant Pool 中，#19 存储这字符串字面量 “abc”，#3 是 String Pool 的字符串对象，它指向 #19 这个字符串字面量。在 main 方法中，0: 行使用 new #2 在堆中创建一个字符串对象，并且使用 ldc #3 将 String Pool 中的字符串对象作为 String 构造函数的参数。</p><p>以下是 String 构造函数的源码，可以看到，在将一个字符串对象作为另一个字符串对象的构造函数参数时，并不会完全复制 value 数组内容，而是都会指向同一个 value 数组。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="title function_">String</span><span class="params">(String original)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.value = original.value;</span><br><span class="line">    <span class="built_in">this</span>.hash = original.hash;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="运算"><a href="#运算" class="headerlink" title="运算"></a>运算</h2><h3 id="参数传递"><a href="#参数传递" class="headerlink" title="参数传递"></a>参数传递</h3><p>Java 的参数是以值传递的形式传入方法中，而不是引用传递。</p><p>以下代码中 Dog dog 的 dog 是一个指针，存储的是对象的地址。在将一个参数传入一个方法时，本质上是将对象的地址以值的方式传递到形参中。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Dog</span> &#123;</span><br><span class="line"></span><br><span class="line">    String name;</span><br><span class="line"></span><br><span class="line">    Dog(String name) &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    String <span class="title function_">getName</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">this</span>.name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(String name)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    String <span class="title function_">getObjectAddress</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">super</span>.toString();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在方法中改变对象的字段值会改变原对象该字段值，因为引用的是同一个对象。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">PassByValueExample</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">Dog</span> <span class="variable">dog</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Dog</span>(<span class="string">&quot;A&quot;</span>);</span><br><span class="line">        func(dog);</span><br><span class="line">        System.out.println(dog.getName());          <span class="comment">// B</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">func</span><span class="params">(Dog dog)</span> &#123;</span><br><span class="line">        dog.setName(<span class="string">&quot;B&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>但是在方法中将指针引用了其它对象，那么此时方法里和方法外的两个指针指向了不同的对象，在一个指针改变其所指向对象的内容对另一个指针所指向的对象没有影响。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PassByValueExample</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">Dog</span> <span class="variable">dog</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Dog</span>(<span class="string">&quot;A&quot;</span>);</span><br><span class="line">        System.out.println(dog.getObjectAddress()); <span class="comment">// Dog@4554617c</span></span><br><span class="line">        func(dog);</span><br><span class="line">        System.out.println(dog.getObjectAddress()); <span class="comment">// Dog@4554617c</span></span><br><span class="line">        System.out.println(dog.getName());          <span class="comment">// A</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">func</span><span class="params">(Dog dog)</span> &#123;</span><br><span class="line">        System.out.println(dog.getObjectAddress()); <span class="comment">// Dog@4554617c</span></span><br><span class="line">        dog = <span class="keyword">new</span> <span class="title class_">Dog</span>(<span class="string">&quot;B&quot;</span>);</span><br><span class="line">        System.out.println(dog.getObjectAddress()); <span class="comment">// Dog@74a14482</span></span><br><span class="line">        System.out.println(dog.getName());          <span class="comment">// B</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>参考：</strong><a href="https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value">StackOverflow: Is Java “pass-by-reference” or “pass-by-value”?</a></p><h3 id="float-与-double"><a href="#float-与-double" class="headerlink" title="float 与 double"></a>float 与 double</h3><p>Java 不能隐式执行向下转型，因为这会使得精度降低。</p><p>1.1 字面量属于 double 类型，不能直接将 1.1 直接赋值给 float 变量，因为这是向下转型。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// float f = 1.1;</span></span><br></pre></td></tr></table></figure><p>1.1f 字面量才是 float 类型。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">float</span> <span class="variable">f</span> <span class="operator">=</span> <span class="number">1.1f</span>;</span><br></pre></td></tr></table></figure><h3 id="隐式类型转换"><a href="#隐式类型转换" class="headerlink" title="隐式类型转换"></a>隐式类型转换</h3><p>因为字面量 1 是 int 类型，它比 short 类型精度要高，因此不能隐式地将 int 类型向下转型为 short 类型。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">short</span> <span class="variable">s1</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"><span class="comment">// s1 = s1 + 1;</span></span><br></pre></td></tr></table></figure><p>但是使用 += 或者 ++ 运算符会执行隐式类型转换。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">s1 += <span class="number">1</span>;</span><br><span class="line">s1++;</span><br></pre></td></tr></table></figure><p>上面的语句相当于将 s1 + 1 的计算结果进行了向下转型：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">s1 = (<span class="type">short</span>) (s1 + <span class="number">1</span>);</span><br></pre></td></tr></table></figure><p><strong>参考：</strong><a href="https://stackoverflow.com/questions/8710619/why-dont-javas-compound-assignment-operators-require-casting">StackOverflow : Why don’t Java’s +=, -=, *=, /= compound assignment operators require casting?</a></p><h3 id="switch"><a href="#switch" class="headerlink" title="switch"></a>switch</h3><p>从 Java 7 开始，可以在 switch 条件判断语句中使用 String 对象。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">s</span> <span class="operator">=</span> <span class="string">&quot;a&quot;</span>;</span><br><span class="line"><span class="keyword">switch</span> (s) &#123;</span><br><span class="line">    <span class="keyword">case</span> <span class="string">&quot;a&quot;</span>:</span><br><span class="line">        System.out.println(<span class="string">&quot;aaa&quot;</span>);</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> <span class="string">&quot;b&quot;</span>:</span><br><span class="line">        System.out.println(<span class="string">&quot;bbb&quot;</span>);</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>switch 不支持 long、float、double，是因为 switch 的设计初衷是对那些只有少数几个值的类型进行等值判断，如果值过于复杂，那么还是用 if 比较合适。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// long x = 111;</span></span><br><span class="line"><span class="comment">// switch (x) &#123; // Incompatible types. Found: &#x27;long&#x27;, required: &#x27;char, byte, short, int, Character, Byte, Short, Integer, String, or an enum&#x27;</span></span><br><span class="line"><span class="comment">//     case 111:</span></span><br><span class="line"><span class="comment">//         System.out.println(111);</span></span><br><span class="line"><span class="comment">//         break;</span></span><br><span class="line"><span class="comment">//     case 222:</span></span><br><span class="line"><span class="comment">//         System.out.println(222);</span></span><br><span class="line"><span class="comment">//         break;</span></span><br><span class="line"><span class="comment">// &#125;</span></span><br></pre></td></tr></table></figure><p><strong>参考：</strong><a href="https://stackoverflow.com/questions/2676210/why-cant-your-switch-statement-data-type-be-long-java">StackOverflow : Why can’t your switch statement data type be long, Java?</a></p><h2 id="关键字"><a href="#关键字" class="headerlink" title="关键字"></a>关键字</h2><h3 id="final"><a href="#final" class="headerlink" title="final"></a>final</h3><ol><li><p>数据</p><p>声明数据为常量，可以是编译时常量，也可以是在运行时被初始化后不能被改变的常量。</p><ul><li>对于基本类型，final 使数值不变；</li><li>对于引用类型，final 使引用不变，也就不能引用其它对象，但是被引用的对象本身是可以修改的。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">final</span> <span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"><span class="comment">// x = 2;  // cannot assign value to final variable &#x27;x&#x27;</span></span><br><span class="line"><span class="keyword">final</span> <span class="type">A</span> <span class="variable">y</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">A</span>();</span><br><span class="line">y.a = <span class="number">1</span>;</span><br></pre></td></tr></table></figure></li><li><p>方法</p><p>声明方法不能被子类重写。</p><p>private 方法隐式地被指定为 final，如果在子类中定义的方法和基类中的一个 private 方法签名相同，此时子类的方法不是重写基类方法，而是在子类中定义了一个新的方法。</p></li><li><p>类</p><p>声明类不允许被继承。</p></li></ol><h3 id="static"><a href="#static" class="headerlink" title="static"></a>static</h3><p><strong>静态变量</strong></p><ul><li>静态变量：又称为类变量，也就是说这个变量属于类的，类所有的实例都共享静态变量，可以直接通过类名来访问它。静态变量在内存中只存在一份。</li><li>实例变量：每创建一个实例就会产生一个实例变量，它与该实例同生共死。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">A</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> x;         <span class="comment">// 实例变量</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">int</span> y;  <span class="comment">// 静态变量</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// int x = A.x;  // Non-static field &#x27;x&#x27; cannot be referenced from a static context</span></span><br><span class="line">        <span class="type">A</span> <span class="variable">a</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">A</span>();</span><br><span class="line">        <span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> a.x;</span><br><span class="line">        <span class="type">int</span> <span class="variable">y</span> <span class="operator">=</span> A.y;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>静态方法</strong></p><p>静态方法在类加载的时候就存在了，它不依赖于任何实例。所以静态方法必须有实现，也就是说它不能是抽象方法。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">A</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">func1</span><span class="params">()</span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// public abstract static void func2();  // Illegal combination of modifiers: &#x27;abstract&#x27; and &#x27;static&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>只能访问所属类的静态字段和静态方法，方法中不能有 this 和 super 关键字，因此这两个关键字与具体对象关联。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">A</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">int</span> x;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> y;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">func1</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">a</span> <span class="operator">=</span> x;</span><br><span class="line">        <span class="comment">// int b = y;  // Non-static field &#x27;y&#x27; cannot be referenced from a static context</span></span><br><span class="line">        <span class="comment">// int b = this.y;     // &#x27;A.this&#x27; cannot be referenced from a static context</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>静态语句块</strong></p><p>静态语句块在类初始化时运行一次。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">A</span> &#123;</span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;123&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">A</span> <span class="variable">a1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">A</span>();</span><br><span class="line">        <span class="type">A</span> <span class="variable">a2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">A</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="number">123</span></span><br></pre></td></tr></table></figure><p><strong>静态内部类</strong></p><p>非静态内部类依赖于外部类的实例，也就是说需要先创建外部类实例，才能用这个实例去创建非静态内部类。而静态内部类不需要。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OuterClass</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">class</span> <span class="title class_">InnerClass</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">StaticInnerClass</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// InnerClass innerClass = new InnerClass(); // &#x27;OuterClass.this&#x27; cannot be referenced from a static context</span></span><br><span class="line">        <span class="type">OuterClass</span> <span class="variable">outerClass</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">OuterClass</span>();</span><br><span class="line">        <span class="type">InnerClass</span> <span class="variable">innerClass</span> <span class="operator">=</span> outerClass.<span class="keyword">new</span> <span class="title class_">InnerClass</span>();</span><br><span class="line">        <span class="type">StaticInnerClass</span> <span class="variable">staticInnerClass</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StaticInnerClass</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>静态内部类不能访问外部类的非静态的变量和方法。</p><p><strong>静态导包</strong></p><p>在使用静态变量和方法时不用再指明 ClassName，从而简化代码，但可读性大大降低。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="keyword">static</span> com.xxx.ClassName.*</span><br></pre></td></tr></table></figure><p><strong>初始化顺序</strong></p><p>静态变量和静态语句块优先于实例变量和普通语句块，静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="type">String</span> <span class="variable">staticField</span> <span class="operator">=</span> <span class="string">&quot;静态变量&quot;</span>;</span><br><span class="line"><span class="keyword">static</span> &#123;</span><br><span class="line">    System.out.println(<span class="string">&quot;静态语句块&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="type">String</span> <span class="variable">field</span> <span class="operator">=</span> <span class="string">&quot;实例变量&quot;</span>;</span><br><span class="line">&#123;</span><br><span class="line">    System.out.println(<span class="string">&quot;普通语句块&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>最后才是构造函数的初始化。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="title function_">InitialOrderTest</span><span class="params">()</span> &#123;</span><br><span class="line">    System.out.println(<span class="string">&quot;构造函数&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>存在继承的情况下，初始化顺序为：</p><ul><li>父类（静态变量、静态语句块）</li><li>子类（静态变量、静态语句块）</li><li>父类（实例变量、普通语句块）</li><li>父类（构造函数）</li><li>子类（实例变量、普通语句块）</li><li>子类（构造函数）</li></ul><h2 id="Object-通用方法"><a href="#Object-通用方法" class="headerlink" title="Object 通用方法"></a>Object 通用方法</h2><h3 id="概览-1"><a href="#概览-1" class="headerlink" title="概览"></a>概览</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">native</span> <span class="type">int</span> <span class="title function_">hashCode</span><span class="params">()</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">equals</span><span class="params">(Object obj)</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">native</span> Object <span class="title function_">clone</span><span class="params">()</span> <span class="keyword">throws</span> CloneNotSupportedException</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">toString</span><span class="params">()</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">native</span> Class&lt;?&gt; getClass()</span><br><span class="line"></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">finalize</span><span class="params">()</span> <span class="keyword">throws</span> Throwable &#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">native</span> <span class="keyword">void</span> <span class="title function_">notify</span><span class="params">()</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">native</span> <span class="keyword">void</span> <span class="title function_">notifyAll</span><span class="params">()</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">native</span> <span class="keyword">void</span> <span class="title function_">wait</span><span class="params">(<span class="type">long</span> timeout)</span> <span class="keyword">throws</span> InterruptedException</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">wait</span><span class="params">(<span class="type">long</span> timeout, <span class="type">int</span> nanos)</span> <span class="keyword">throws</span> InterruptedException</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">wait</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException</span><br></pre></td></tr></table></figure><h3 id="equals"><a href="#equals" class="headerlink" title="equals()"></a>equals()</h3><p><strong>等价关系</strong></p><p>两个对象具有等价关系，需要满足以下五个条件：</p><p>自反性</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">x.equals(x); <span class="comment">// true</span></span><br></pre></td></tr></table></figure><p>对称性</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">x.equals(y) == y.equals(x); <span class="comment">// true</span></span><br></pre></td></tr></table></figure><p>传递性</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (x.equals(y) &amp;&amp; y.equals(z))</span><br><span class="line">    x.equals(z); <span class="comment">// true;</span></span><br></pre></td></tr></table></figure><p>一致性</p><p>多次调用 equals() 方法结果不变</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">x.equals(y) == x.equals(y); <span class="comment">// true</span></span><br></pre></td></tr></table></figure><p>与 null 的比较</p><p>对任何不是 null 的对象 x 调用 x.equals(null) 结果都为 false</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">x.equals(<span class="literal">null</span>); <span class="comment">// false;</span></span><br></pre></td></tr></table></figure><p><strong>等价与相等</strong></p><ul><li>对于基本类型，== 判断两个值是否相等，基本类型没有 equals() 方法。</li><li>对于引用类型，== 判断两个变量是否引用同一个对象，而 equals() 判断引用的对象是否等价。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">Integer</span> <span class="variable">x</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Integer</span>(<span class="number">1</span>);</span><br><span class="line"><span class="type">Integer</span> <span class="variable">y</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Integer</span>(<span class="number">1</span>);</span><br><span class="line">System.out.println(x.equals(y)); <span class="comment">// true</span></span><br><span class="line">System.out.println(x == y);      <span class="comment">// false</span></span><br></pre></td></tr></table></figure><p><strong>实现</strong></p><ul><li>检查是否为同一个对象的引用，如果是直接返回 true；</li><li>检查是否是同一个类型，如果不是，直接返回 false；</li><li>将 Object 对象进行转型；</li><li>判断每个关键域是否相等。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">EqualExample</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> x;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> y;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> z;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">EqualExample</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y, <span class="type">int</span> z)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.x = x;</span><br><span class="line">        <span class="built_in">this</span>.y = y;</span><br><span class="line">        <span class="built_in">this</span>.z = z;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">equals</span><span class="params">(Object o)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="built_in">this</span> == o) <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        <span class="keyword">if</span> (o == <span class="literal">null</span> || getClass() != o.getClass()) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">        <span class="type">EqualExample</span> <span class="variable">that</span> <span class="operator">=</span> (EqualExample) o;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (x != that.x) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        <span class="keyword">if</span> (y != that.y) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        <span class="keyword">return</span> z == that.z;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="hashCode"><a href="#hashCode" class="headerlink" title="hashCode()"></a>hashCode()</h3><p>hashCode() 返回哈希值，而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同，但是散列值相同的两个对象不一定等价，这是因为计算哈希值具有随机性，两个值不同的对象可能计算出相同的哈希值。</p><p>在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法，保证等价的两个对象哈希值也相等。</p><p>HashSet 和 HashMap 等集合类使用了 hashCode() 方法来计算对象应该存储的位置，因此要将对象添加到这些集合类中，需要让对应的类实现 hashCode() 方法。</p><p>下面的代码中，新建了两个等价的对象，并将它们添加到 HashSet 中。我们希望将这两个对象当成一样的，只在集合中添加一个对象。但是 EqualExample 没有实现 hashCode() 方法，因此这两个对象的哈希值是不同的，最终导致集合添加了两个等价的对象。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">EqualExample</span> <span class="variable">e1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">EqualExample</span>(<span class="number">1</span>, <span class="number">1</span>, <span class="number">1</span>);</span><br><span class="line"><span class="type">EqualExample</span> <span class="variable">e2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">EqualExample</span>(<span class="number">1</span>, <span class="number">1</span>, <span class="number">1</span>);</span><br><span class="line">System.out.println(e1.equals(e2)); <span class="comment">// true</span></span><br><span class="line">HashSet&lt;EqualExample&gt; set = <span class="keyword">new</span> <span class="title class_">HashSet</span>&lt;&gt;();</span><br><span class="line">set.add(e1);</span><br><span class="line">set.add(e2);</span><br><span class="line">System.out.println(set.size());   <span class="comment">// 2</span></span><br></pre></td></tr></table></figure><p>理想的哈希函数应当具有均匀性，即不相等的对象应当均匀分布到所有可能的哈希值上。这就要求了哈希函数要把所有域的值都考虑进来。可以将每个域都当成 R 进制的某一位，然后组成一个 R 进制的整数。</p><p>R 一般取 31，因为它是一个奇素数，如果是偶数的话，当出现乘法溢出，信息就会丢失，因为与 2 相乘相当于向左移一位，最左边的位丢失。并且一个数与 31 相乘可以转换成移位和减法：<code>31*x == (x&lt;&lt;5)-x</code>，编译器会自动进行这个优化。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">int</span> <span class="title function_">hashCode</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> <span class="number">17</span>;</span><br><span class="line">    result = <span class="number">31</span> * result + x;</span><br><span class="line">    result = <span class="number">31</span> * result + y;</span><br><span class="line">    result = <span class="number">31</span> * result + z;</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="toString-NaN"><a href="#toString-NaN" class="headerlink" title="toString()"></a>toString()</h3><p>默认返回 ToStringExample@4554617c 这种形式，其中 @ 后面的数值为散列码的无符号十六进制表示。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ToStringExample</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> number;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">ToStringExample</span><span class="params">(<span class="type">int</span> number)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.number = number;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">ToStringExample</span> <span class="variable">example</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ToStringExample</span>(<span class="number">123</span>);</span><br><span class="line">System.out.println(example.toString());</span><br><span class="line">ToStringExample@4554617c</span><br></pre></td></tr></table></figure><h3 id="clone"><a href="#clone" class="headerlink" title="clone()"></a>clone()</h3><p><strong>cloneable</strong></p><p>clone() 是 Object 的 protected 方法，它不是 public，一个类不显式去重写 clone()，其它类就不能直接去调用该类实例的 clone() 方法。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CloneExample</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> a;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> b;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">CloneExample</span> <span class="variable">e1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CloneExample</span>();</span><br><span class="line"><span class="comment">// CloneExample e2 = e1.clone(); // &#x27;clone()&#x27; has protected access in &#x27;java.lang.Object&#x27;</span></span><br></pre></td></tr></table></figure><p>重写 clone() 得到以下实现：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CloneExample</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> a;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> b;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> CloneExample <span class="title function_">clone</span><span class="params">()</span> <span class="keyword">throws</span> CloneNotSupportedException &#123;</span><br><span class="line">        <span class="keyword">return</span> (CloneExample)<span class="built_in">super</span>.clone();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">CloneExample</span> <span class="variable">e1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CloneExample</span>();</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="type">CloneExample</span> <span class="variable">e2</span> <span class="operator">=</span> e1.clone();</span><br><span class="line">&#125; <span class="keyword">catch</span> (CloneNotSupportedException e) &#123;</span><br><span class="line">    e.printStackTrace();</span><br><span class="line">&#125;</span><br><span class="line">java.lang.CloneNotSupportedException: CloneExample</span><br></pre></td></tr></table></figure><p>以上抛出了 CloneNotSupportedException，这是因为 CloneExample 没有实现 Cloneable 接口。</p><p>应该注意的是，clone() 方法并不是 Cloneable 接口的方法，而是 Object 的一个 protected 方法。Cloneable 接口只是规定，如果一个类没有实现 Cloneable 接口又调用了 clone() 方法，就会抛出 CloneNotSupportedException。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CloneExample</span> <span class="keyword">implements</span> <span class="title class_">Cloneable</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> a;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> b;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">clone</span><span class="params">()</span> <span class="keyword">throws</span> CloneNotSupportedException &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">super</span>.clone();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>浅拷贝</strong></p><p>拷贝对象和原始对象的引用类型引用同一个对象。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ShallowCloneExample</span> <span class="keyword">implements</span> <span class="title class_">Cloneable</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span>[] arr;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">ShallowCloneExample</span><span class="params">()</span> &#123;</span><br><span class="line">        arr = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="number">10</span>];</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; arr.length; i++) &#123;</span><br><span class="line">            arr[i] = i;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">set</span><span class="params">(<span class="type">int</span> index, <span class="type">int</span> value)</span> &#123;</span><br><span class="line">        arr[index] = value;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">get</span><span class="params">(<span class="type">int</span> index)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> arr[index];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> ShallowCloneExample <span class="title function_">clone</span><span class="params">()</span> <span class="keyword">throws</span> CloneNotSupportedException &#123;</span><br><span class="line">        <span class="keyword">return</span> (ShallowCloneExample) <span class="built_in">super</span>.clone();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">ShallowCloneExample</span> <span class="variable">e1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ShallowCloneExample</span>();</span><br><span class="line"><span class="type">ShallowCloneExample</span> <span class="variable">e2</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    e2 = e1.clone();</span><br><span class="line">&#125; <span class="keyword">catch</span> (CloneNotSupportedException e) &#123;</span><br><span class="line">    e.printStackTrace();</span><br><span class="line">&#125;</span><br><span class="line">e1.set(<span class="number">2</span>, <span class="number">222</span>);</span><br><span class="line">System.out.println(e2.get(<span class="number">2</span>)); <span class="comment">// 222</span></span><br></pre></td></tr></table></figure><p><strong>深拷贝</strong></p><p>拷贝对象和原始对象的引用类型引用不同对象。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DeepCloneExample</span> <span class="keyword">implements</span> <span class="title class_">Cloneable</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span>[] arr;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">DeepCloneExample</span><span class="params">()</span> &#123;</span><br><span class="line">        arr = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="number">10</span>];</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; arr.length; i++) &#123;</span><br><span class="line">            arr[i] = i;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">set</span><span class="params">(<span class="type">int</span> index, <span class="type">int</span> value)</span> &#123;</span><br><span class="line">        arr[index] = value;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">get</span><span class="params">(<span class="type">int</span> index)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> arr[index];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> DeepCloneExample <span class="title function_">clone</span><span class="params">()</span> <span class="keyword">throws</span> CloneNotSupportedException &#123;</span><br><span class="line">        <span class="type">DeepCloneExample</span> <span class="variable">result</span> <span class="operator">=</span> (DeepCloneExample) <span class="built_in">super</span>.clone();</span><br><span class="line">        result.arr = <span class="keyword">new</span> <span class="title class_">int</span>[arr.length];</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; arr.length; i++) &#123;</span><br><span class="line">            result.arr[i] = arr[i];</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">DeepCloneExample</span> <span class="variable">e1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DeepCloneExample</span>();</span><br><span class="line"><span class="type">DeepCloneExample</span> <span class="variable">e2</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    e2 = e1.clone();</span><br><span class="line">&#125; <span class="keyword">catch</span> (CloneNotSupportedException e) &#123;</span><br><span class="line">    e.printStackTrace();</span><br><span class="line">&#125;</span><br><span class="line">e1.set(<span class="number">2</span>, <span class="number">222</span>);</span><br><span class="line">System.out.println(e2.get(<span class="number">2</span>)); <span class="comment">// 2</span></span><br></pre></td></tr></table></figure><p><strong>clone() 的替代方案</strong></p><p>使用 clone() 方法来拷贝一个对象即复杂又有风险，它会抛出异常，并且还需要类型转换。Effective Java 书上讲到，最好不要去使用 clone()，可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CloneConstructorExample</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span>[] arr;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">CloneConstructorExample</span><span class="params">()</span> &#123;</span><br><span class="line">        arr = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="number">10</span>];</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; arr.length; i++) &#123;</span><br><span class="line">            arr[i] = i;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">CloneConstructorExample</span><span class="params">(CloneConstructorExample original)</span> &#123;</span><br><span class="line">        arr = <span class="keyword">new</span> <span class="title class_">int</span>[original.arr.length];</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; original.arr.length; i++) &#123;</span><br><span class="line">            arr[i] = original.arr[i];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">set</span><span class="params">(<span class="type">int</span> index, <span class="type">int</span> value)</span> &#123;</span><br><span class="line">        arr[index] = value;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">get</span><span class="params">(<span class="type">int</span> index)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> arr[index];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">CloneConstructorExample</span> <span class="variable">e1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CloneConstructorExample</span>();</span><br><span class="line"><span class="type">CloneConstructorExample</span> <span class="variable">e2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CloneConstructorExample</span>(e1);</span><br><span class="line">e1.set(<span class="number">2</span>, <span class="number">222</span>);</span><br><span class="line">System.out.println(e2.get(<span class="number">2</span>)); <span class="comment">// 2</span></span><br></pre></td></tr></table></figure><h2 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h2><h3 id="访问权限"><a href="#访问权限" class="headerlink" title="访问权限"></a>访问权限</h3><p>Java 中有三个访问权限修饰符：private、protected 以及 public，如果不加访问修饰符，表示包级可见。</p><p>可以对类或类中的成员（字段和方法）加上访问修饰符。</p><ul><li>类可见表示其它类可以用这个类创建实例对象。</li><li>成员可见表示其它类可以用这个类的实例对象访问到该成员；</li></ul><p>protected 用于修饰成员，表示在继承体系中成员对于子类可见，但是这个访问修饰符对于类没有意义。</p><p>设计良好的模块会隐藏所有的实现细节，把它的 API 与它的实现清晰地隔离开来。模块之间只通过它们的 API 进行通信，一个模块不需要知道其他模块的内部工作情况，这个概念被称为信息隐藏或封装。因此访问权限应当尽可能地使每个类或者成员不被外界访问。</p><p>如果子类的方法重写了父类的方法，那么子类中该方法的访问级别不允许低于父类的访问级别。这是为了确保可以使用父类实例的地方都可以使用子类实例去代替，也就是确保满足里氏替换原则。</p><p>字段决不能是公有的，因为这么做的话就失去了对这个字段修改行为的控制，客户端可以对其随意修改。例如下面的例子中，AccessExample 拥有 id 公有字段，如果在某个时刻，我们想要使用 int 存储 id 字段，那么就需要修改所有的客户端代码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccessExample</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> String id;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>可以使用公有的 getter 和 setter 方法来替换公有字段，这样的话就可以控制对字段的修改行为。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccessExample</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> id;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">getId</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> id + <span class="string">&quot;&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setId</span><span class="params">(String id)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.id = Integer.valueOf(id);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>但是也有例外，如果是包级私有的类或者私有的嵌套类，那么直接暴露成员不会有特别大的影响。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccessWithInnerClassExample</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">class</span> <span class="title class_">InnerClass</span> &#123;</span><br><span class="line">        <span class="type">int</span> x;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> InnerClass innerClass;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">AccessWithInnerClassExample</span><span class="params">()</span> &#123;</span><br><span class="line">        innerClass = <span class="keyword">new</span> <span class="title class_">InnerClass</span>();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">getValue</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> innerClass.x;  <span class="comment">// 直接访问</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="抽象类与接口"><a href="#抽象类与接口" class="headerlink" title="抽象类与接口"></a>抽象类与接口</h3><p><strong>1. 抽象类</strong></p><p>抽象类和抽象方法都使用 abstract 关键字进行声明。如果一个类中包含抽象方法，那么这个类必须声明为抽象类。</p><p>抽象类和普通类最大的区别是，抽象类不能被实例化，只能被继承。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">AbstractClassExample</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">protected</span> <span class="type">int</span> x;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> y;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">func1</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">func2</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;func2&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AbstractExtendClassExample</span> <span class="keyword">extends</span> <span class="title class_">AbstractClassExample</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">func1</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;func1&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// AbstractClassExample ac1 = new AbstractClassExample(); // &#x27;AbstractClassExample&#x27; is abstract; cannot be instantiated</span></span><br><span class="line"><span class="type">AbstractClassExample</span> <span class="variable">ac2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AbstractExtendClassExample</span>();</span><br><span class="line">ac2.func1();</span><br></pre></td></tr></table></figure><p><strong>2. 接口</strong></p><p>接口是抽象类的延伸，在 Java 8 之前，它可以看成是一个完全抽象的类，也就是说它不能有任何的方法实现。</p><p>从 Java 8 开始，接口也可以拥有默认的方法实现，这是因为不支持默认方法的接口的维护成本太高了。在 Java 8 之前，如果一个接口想要添加新的方法，那么要修改所有实现了该接口的类，让它们都实现新增的方法。</p><p>接口的成员（字段 + 方法）默认都是 public 的，并且不允许定义为 private 或者 protected。从 Java 9 开始，允许将方法定义为 private，这样就能定义某些复用的代码又不会把方法暴露出去。</p><p>接口的字段默认都是 static 和 final 的。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">InterfaceExample</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">func1</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">default</span> <span class="keyword">void</span> <span class="title function_">func2</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;func2&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">123</span>;</span><br><span class="line">    <span class="comment">// int y;               // Variable &#x27;y&#x27; might not have been initialized</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="variable">z</span> <span class="operator">=</span> <span class="number">0</span>;       <span class="comment">// Modifier &#x27;public&#x27; is redundant for interface fields</span></span><br><span class="line">    <span class="comment">// private int k = 0;   // Modifier &#x27;private&#x27; not allowed here</span></span><br><span class="line">    <span class="comment">// protected int l = 0; // Modifier &#x27;protected&#x27; not allowed here</span></span><br><span class="line">    <span class="comment">// private void fun3(); // Modifier &#x27;private&#x27; not allowed here</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">InterfaceImplementExample</span> <span class="keyword">implements</span> <span class="title class_">InterfaceExample</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">func1</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;func1&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// InterfaceExample ie1 = new InterfaceExample(); // &#x27;InterfaceExample&#x27; is abstract; cannot be instantiated</span></span><br><span class="line"><span class="type">InterfaceExample</span> <span class="variable">ie2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">InterfaceImplementExample</span>();</span><br><span class="line">ie2.func1();</span><br><span class="line">System.out.println(InterfaceExample.x);</span><br></pre></td></tr></table></figure><p><strong>3. 比较</strong></p><ul><li>从设计层面上看，抽象类提供了一种 IS-A 关系，需要满足里式替换原则，即子类对象必须能够替换掉所有父类对象。而接口更像是一种 LIKE-A 关系，它只是提供一种方法实现契约，并不要求接口和实现接口的类具有 IS-A 关系。</li><li>从使用上来看，一个类可以实现多个接口，但是不能继承多个抽象类。</li><li>接口的字段只能是 static 和 final 类型的，而抽象类的字段没有这种限制。</li><li>接口的成员只能是 public 的，而抽象类的成员可以有多种访问权限。</li></ul><p><strong>4. 使用选择</strong></p><p>使用接口：</p><ul><li>需要让不相关的类都实现一个方法，例如不相关的类都可以实现 Comparable 接口中的 compareTo() 方法；</li><li>需要使用多重继承。</li></ul><p>使用抽象类：</p><ul><li>需要在几个相关的类中共享代码。</li><li>需要能控制继承来的成员的访问权限，而不是都为 public。</li><li>需要继承非静态和非常量字段。</li></ul><p>在很多情况下，接口优先于抽象类。因为接口没有抽象类严格的类层次结构要求，可以灵活地为一个类添加行为。并且从 Java 8 开始，接口也可以有默认的方法实现，使得修改接口的成本也变的很低。</p><p><strong>参考：</strong></p><ul><li><a href="https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html">Abstract Methods and Classes</a></li><li><a href="https://www.ibm.com/developerworks/cn/java/l-javainterface-abstract/">深入理解 abstract class 和 interface</a></li><li><a href="https://dzone.com/articles/when-to-use-abstract-class-and-intreface">When to Use Abstract Class and Interface</a></li><li><a href="https://www.journaldev.com/12850/java-9-private-methods-interfaces">Java 9 Private Methods in Interfaces</a></li></ul><h3 id="super"><a href="#super" class="headerlink" title="super"></a>super</h3><ul><li>访问父类的构造函数：可以使用 super() 函数访问父类的构造函数，从而委托父类完成一些初始化的工作。应该注意到，子类一定会调用父类的构造函数来完成初始化工作，一般是调用父类的默认构造函数，如果子类需要调用父类其它构造函数，那么就可以使用 super() 函数。</li><li>访问父类的成员：如果子类重写了父类的某个方法，可以通过使用 super 关键字来引用父类的方法实现。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SuperExample</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">protected</span> <span class="type">int</span> x;</span><br><span class="line">    <span class="keyword">protected</span> <span class="type">int</span> y;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">SuperExample</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.x = x;</span><br><span class="line">        <span class="built_in">this</span>.y = y;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">func</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;SuperExample.func()&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SuperExtendExample</span> <span class="keyword">extends</span> <span class="title class_">SuperExample</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> z;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">SuperExtendExample</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y, <span class="type">int</span> z)</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>(x, y);</span><br><span class="line">        <span class="built_in">this</span>.z = z;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">func</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>.func();</span><br><span class="line">        System.out.println(<span class="string">&quot;SuperExtendExample.func()&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">SuperExample</span> <span class="variable">e</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SuperExtendExample</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>);</span><br><span class="line">e.func();</span><br><span class="line">SuperExample.func()</span><br><span class="line">SuperExtendExample.func()</span><br></pre></td></tr></table></figure><p><strong>参考：</strong><a href="https://docs.oracle.com/javase/tutorial/java/IandI/super.html">Using the Keyword super</a></p><h3 id="重写与重载"><a href="#重写与重载" class="headerlink" title="重写与重载"></a>重写与重载</h3><p><strong>1. 重写（Override）</strong></p><p>存在于继承体系中，指子类实现了一个与父类在方法声明上完全相同的一个方法。</p><p>为了满足里式替换原则，重写有以下三个限制：</p><ul><li>子类方法的访问权限必须大于等于父类方法；</li><li>子类方法的返回类型必须是父类方法返回类型或为其子类型。</li><li>子类方法抛出的异常类型必须是父类抛出异常类型或为其子类型。</li></ul><p>使用 <code>@Override</code> 注解，可以让编译器帮忙检查是否满足上面的三个限制条件。</p><p>下面的示例中，SubClass 为 SuperClass 的子类，SubClass 重写了 SuperClass 的 func() 方法。其中：</p><ul><li>子类方法访问权限为 public，大于父类的 protected。</li><li>子类的返回类型为 <code>ArrayList&lt;Integer&gt;</code>，是父类返回类型 <code>List&lt;Integer&gt;</code> 的子类。</li><li>子类抛出的异常类型为 Exception，是父类抛出异常 Throwable 的子类。</li><li>子类重写方法使用 @Override 注解，从而让编译器自动检查是否满足限制条件。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">SuperClass</span> &#123;</span><br><span class="line">    <span class="keyword">protected</span> List&lt;Integer&gt; <span class="title function_">func</span><span class="params">()</span> <span class="keyword">throws</span> Throwable &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">SubClass</span> <span class="keyword">extends</span> <span class="title class_">SuperClass</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> ArrayList&lt;Integer&gt; <span class="title function_">func</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在调用一个方法时，先从本类中查找看是否有对应的方法，如果没有再到父类中查看，看是否从父类继承来。否则就要对参数进行转型，转成父类之后看是否有对应的方法。总的来说，方法调用的优先级为：</p><ul><li>this.func(this)</li><li>super.func(this)</li><li>this.func(super)</li><li>super.func(super)</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">    A</span></span><br><span class="line"><span class="comment">    |</span></span><br><span class="line"><span class="comment">    B</span></span><br><span class="line"><span class="comment">    |</span></span><br><span class="line"><span class="comment">    C</span></span><br><span class="line"><span class="comment">    |</span></span><br><span class="line"><span class="comment">    D</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">A</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">show</span><span class="params">(A obj)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;A.show(A)&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">show</span><span class="params">(C obj)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;A.show(C)&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">B</span> <span class="keyword">extends</span> <span class="title class_">A</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">show</span><span class="params">(A obj)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;B.show(A)&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">C</span> <span class="keyword">extends</span> <span class="title class_">B</span> &#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">D</span> <span class="keyword">extends</span> <span class="title class_">C</span> &#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="type">A</span> <span class="variable">a</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">A</span>();</span><br><span class="line">    <span class="type">B</span> <span class="variable">b</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">B</span>();</span><br><span class="line">    <span class="type">C</span> <span class="variable">c</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">C</span>();</span><br><span class="line">    <span class="type">D</span> <span class="variable">d</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">D</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 在 A 中存在 show(A obj)，直接调用</span></span><br><span class="line">    a.show(a); <span class="comment">// A.show(A)</span></span><br><span class="line">    <span class="comment">// 在 A 中不存在 show(B obj)，将 B 转型成其父类 A</span></span><br><span class="line">    a.show(b); <span class="comment">// A.show(A)</span></span><br><span class="line">    <span class="comment">// 在 B 中存在从 A 继承来的 show(C obj)，直接调用</span></span><br><span class="line">    b.show(c); <span class="comment">// A.show(C)</span></span><br><span class="line">    <span class="comment">// 在 B 中不存在 show(D obj)，但是存在从 A 继承来的 show(C obj)，将 D 转型成其父类 C</span></span><br><span class="line">    b.show(d); <span class="comment">// A.show(C)</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 引用的还是 B 对象，所以 ba 和 b 的调用结果一样</span></span><br><span class="line">    <span class="type">A</span> <span class="variable">ba</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">B</span>();</span><br><span class="line">    ba.show(c); <span class="comment">// A.show(C)</span></span><br><span class="line">    ba.show(d); <span class="comment">// A.show(C)</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>2. 重载（Overload）</strong></p><p>存在于同一个类中，指一个方法与已经存在的方法名称上相同，但是参数类型、个数、顺序至少有一个不同。</p><p>应该注意的是，返回值不同，其它都相同不算是重载。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">OverloadingExample</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">show</span><span class="params">(<span class="type">int</span> x)</span> &#123;</span><br><span class="line">        System.out.println(x);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">show</span><span class="params">(<span class="type">int</span> x, String y)</span> &#123;</span><br><span class="line">        System.out.println(x + <span class="string">&quot; &quot;</span> + y);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">    <span class="type">OverloadingExample</span> <span class="variable">example</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">OverloadingExample</span>();</span><br><span class="line">    example.show(<span class="number">1</span>);</span><br><span class="line">    example.show(<span class="number">1</span>, <span class="string">&quot;2&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="反射"><a href="#反射" class="headerlink" title="反射"></a>反射</h2><p>每个类都有一个 <strong>Class</strong> 对象，包含了与类有关的信息。当编译一个新类时，会产生一个同名的 .class 文件，该文件内容保存着 Class 对象。</p><p>类加载相当于 Class 对象的加载，类在第一次使用时才动态加载到 JVM 中。也可以使用 <code>Class.forName(&quot;com.mysql.jdbc.Driver&quot;)</code> 这种方式来控制类的加载，该方法会返回一个 Class 对象。</p><p>反射可以提供运行时的类信息，并且这个类可以在运行时才加载进来，甚至在编译时期该类的 .class 不存在也可以加载进来。</p><p>Class 和 java.lang.reflect 一起对反射提供了支持，java.lang.reflect 类库主要包含了以下三个类：</p><ul><li><strong>Field</strong> ：可以使用 get() 和 set() 方法读取和修改 Field 对象关联的字段；</li><li><strong>Method</strong> ：可以使用 invoke() 方法调用与 Method 对象关联的方法；</li><li><strong>Constructor</strong> ：可以用 Constructor 的 newInstance() 创建新的对象。</li></ul><p><strong>反射的优点：</strong></p><ul><li><strong>可扩展性</strong> ：应用程序可以利用全限定名创建可扩展对象的实例，来使用来自外部的用户自定义类。</li><li><strong>类浏览器和可视化开发环境</strong> ：一个类浏览器需要可以枚举类的成员。可视化开发环境（如 IDE）可以从利用反射中可用的类型信息中受益，以帮助程序员编写正确的代码。</li><li><strong>调试器和测试工具</strong> ： 调试器需要能够检查一个类里的私有成员。测试工具可以利用反射来自动地调用类里定义的可被发现的 API 定义，以确保一组测试中有较高的代码覆盖率。</li></ul><p><strong>反射的缺点：</strong></p><p>尽管反射非常强大，但也不能滥用。如果一个功能可以不用反射完成，那么最好就不用。在我们使用反射技术时，下面几条内容应该牢记于心。</p><ul><li><strong>性能开销</strong> ：反射涉及了动态类型的解析，所以 JVM 无法对这些代码进行优化。因此，反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。</li><li><strong>安全限制</strong> ：使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行，如 Applet，那么这就是个问题了。</li><li><strong>内部暴露</strong> ：由于反射允许代码执行一些在正常情况下不被允许的操作（比如访问私有的属性和方法），所以使用反射可能会导致意料之外的副作用，这可能导致代码功能失调并破坏可移植性。反射代码破坏了抽象性，因此当平台发生改变的时候，代码的行为就有可能也随着变化。</li></ul><p><strong>参考：</strong></p><ul><li><a href="https://docs.oracle.com/javase/tutorial/reflect/index.html">Trail: The Reflection API</a></li><li><a href="http://www.sczyh30.com/posts/Java/java-reflection-1/">深入解析 Java 反射（1）- 基础</a></li></ul><h2 id="异常"><a href="#异常" class="headerlink" title="异常"></a>异常</h2><p>Throwable 可以用来表示任何可以作为异常抛出的类，分为两种： <strong>Error</strong> 和 <strong>Exception</strong>。其中 Error 用来表示 JVM 无法处理的错误，Exception 分为两种：</p><ul><li><p><strong>受检异常</strong>：需要用 <code>try...catch...</code> 语句捕获并进行处理，并且可以从异常中恢复；</p></li><li><p><strong>非受检异常</strong>：是程序运行时错误，例如除 0 会引发 <code>Arithmetic Exception</code>，此时程序崩溃并且无法恢复。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/java-basics/java48825f9b84c84.webp" alt="img"></p></li></ul><p><strong>参考：</strong></p><ul><li><a href="https://www.cnblogs.com/Blue-Keroro/p/8875898.html">Java 入门之异常处理(opens new window)</a></li><li><a href="https://www.journaldev.com/2167/java-exception-interview-questions-and-answersl">Java Exception Interview Questions and Answers(opens new window)</a></li></ul><h2 id="泛型"><a href="#泛型" class="headerlink" title="泛型"></a>泛型</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Box</span>&lt;T&gt; &#123;</span><br><span class="line">    <span class="comment">// T stands for &quot;Type&quot;</span></span><br><span class="line">    <span class="keyword">private</span> T t;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">set</span><span class="params">(T t)</span> &#123; <span class="built_in">this</span>.t = t; &#125;</span><br><span class="line">    <span class="keyword">public</span> T <span class="title function_">get</span><span class="params">()</span> &#123; <span class="keyword">return</span> t; &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>参考：</strong></p><ul><li><a href="https://www.cnblogs.com/Blue-Keroro/p/8875898.html">Java 泛型详解</a></li><li><a href="https://cloud.tencent.com/developer/article/1033693">10 道 Java 泛型面试题</a></li></ul><h2 id="注解"><a href="#注解" class="headerlink" title="注解"></a>注解</h2><p>Java 注解是附加在代码中的一些元信息，用于一些工具在编译、运行时进行解析和使用，起到说明、配置的功能。注解不会也不能影响代码的实际逻辑，仅仅起到辅助性的作用。</p><p><strong>参考：</strong></p><ul><li><a href="https://www.cnblogs.com/acm-bingzi/p/javaAnnotation.html">注解 Annotation 实现原理与自定义注解例子</a></li></ul><h2 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h2><h3 id="Java-各版本的新特性"><a href="#Java-各版本的新特性" class="headerlink" title="Java 各版本的新特性"></a>Java 各版本的新特性</h3><p><strong>New highlights in Java SE 8</strong></p><ol><li>Lambda Expressions</li><li>Pipelines and Streams</li><li>Date and Time API</li><li>Default Methods</li><li>Type Annotations</li><li>Nashhorn JavaScript Engine</li><li>Concurrent Accumulators</li><li>Parallel operations</li><li>PermGen Error Removed</li></ol><p><strong>New highlights in Java SE 7</strong></p><ol><li>Strings in Switch Statement</li><li>Type Inference for Generic Instance Creation</li><li>Multiple Exception Handling</li><li>Support for Dynamic Languages</li><li>Try with Resources</li><li>Java nio Package</li><li>Binary Literals, Underscore in literals</li><li>Diamond Syntax</li></ol><ul><li><a href="http://www.selfgrowth.com/articles/difference-between-java-18-and-java-17">Difference between Java 1.8 and Java 1.7?</a></li><li><a href="http://www.importnew.com/19345.html">Java 8 特性</a></li></ul><h3 id="Java-与-C-的区别"><a href="#Java-与-C-的区别" class="headerlink" title="Java 与 C++ 的区别"></a>Java 与 C++ 的区别</h3><ul><li>Java 是纯粹的面向对象语言，所有的对象都继承自 java.lang.Object，C++ 为了兼容 C 即支持面向对象也支持面向过程。</li><li>Java 通过虚拟机从而实现跨平台特性，但是 C++ 依赖于特定的平台。</li><li>Java 没有指针，它的引用可以理解为安全指针，而 C++ 具有和 C 一样的指针。</li><li>Java 支持自动垃圾回收，而 C++ 需要手动回收。</li><li>Java 不支持多重继承，只能通过实现多个接口来达到相同目的，而 C++ 支持多重继承。</li><li>Java 不支持操作符重载，虽然可以对两个 String 对象执行加法运算，但是这是语言内置支持的操作，不属于操作符重载，而 C++ 可以。</li><li>Java 的 goto 是保留字，但是不可用，C++ 可以使用 goto。</li></ul><p><strong>参考：</strong><a href="http://cs-fundamentals.com/tech-interview/java/differences-between-java-and-cpp.php">What are the main differences between Java and C++?</a></p><h3 id="JRE-or-JDK"><a href="#JRE-or-JDK" class="headerlink" title="JRE or JDK"></a>JRE or JDK</h3><ul><li>JRE：Java Runtime Environment，Java 运行环境的简称，为 Java 的运行提供了所需的环境。它是一个 JVM 程序，主要包括了 JVM 的标准实现和一些 Java 基本类库。</li><li>JDK：Java Development Kit，Java 开发工具包，提供了 Java 的开发及运行环境。JDK 是 Java 开发的核心，集成了 JRE 以及一些其它的工具，比如编译 Java 源码的编译器 javac 等。</li></ul><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ul><li>Eckel B. Java 编程思想[M]. 机械工业出版社, 2002.</li><li>Bloch J. Effective java[M]. Addison-Wesley Professional, 2017.</li></ul>]]></content>
    
    
    <summary type="html">Java提供了八种基本类型。六种数字类型（四个整数型，两个浮点型），一种字符类型，还有一种布尔型。boolean只有两个值：true、false，可以使用 1 bit 来存储，但是具体大小没有明确规定。</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Java" scheme="https://blog.imzjw.cn/tags/Java/"/>
    
  </entry>
  
  <entry>
    <title>SQL 练习题</title>
    <link href="https://blog.imzjw.cn/posts/sql-exercises/"/>
    <id>https://blog.imzjw.cn/posts/sql-exercises/</id>
    <published>2020-12-03T07:00:56.000Z</published>
    <updated>2020-12-03T07:00:56.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Big-Countries"><a href="#Big-Countries" class="headerlink" title="Big Countries"></a>Big Countries</h2><p>原题：<a href="https://leetcode.com/problems/big-countries/description">https://leetcode.com/problems/big-countries/description</a></p><p>创建表结构</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span></span><br><span class="line">IF</span><br><span class="line">    <span class="keyword">EXISTS</span> World;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> World ( NAME <span class="type">VARCHAR</span> ( <span class="number">255</span> ), continent <span class="type">VARCHAR</span> ( <span class="number">255</span> ), area <span class="type">INT</span>, population <span class="type">INT</span>, gdp <span class="type">INT</span> );</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> World ( NAME, continent, area, population, gdp )</span><br><span class="line"><span class="keyword">VALUES</span></span><br><span class="line">    ( <span class="string">&#x27;Afghanistan&#x27;</span>, <span class="string">&#x27;Asia&#x27;</span>, <span class="string">&#x27;652230&#x27;</span>, <span class="string">&#x27;25500100&#x27;</span>, <span class="string">&#x27;203430000&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;Albania&#x27;</span>, <span class="string">&#x27;Europe&#x27;</span>, <span class="string">&#x27;28748&#x27;</span>, <span class="string">&#x27;2831741&#x27;</span>, <span class="string">&#x27;129600000&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;Algeria&#x27;</span>, <span class="string">&#x27;Africa&#x27;</span>, <span class="string">&#x27;2381741&#x27;</span>, <span class="string">&#x27;37100000&#x27;</span>, <span class="string">&#x27;1886810000&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;Andorra&#x27;</span>, <span class="string">&#x27;Europe&#x27;</span>, <span class="string">&#x27;468&#x27;</span>, <span class="string">&#x27;78115&#x27;</span>, <span class="string">&#x27;37120000&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;Angola&#x27;</span>, <span class="string">&#x27;Africa&#x27;</span>, <span class="string">&#x27;1246700&#x27;</span>, <span class="string">&#x27;20609294&#x27;</span>, <span class="string">&#x27;1009900000&#x27;</span> );</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">-----------------+------------+------------+--------------+---------------+</span></span><br><span class="line"><span class="operator">|</span> name            <span class="operator">|</span> continent  <span class="operator">|</span> area       <span class="operator">|</span> population   <span class="operator">|</span> gdp           <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">-----------------+------------+------------+--------------+---------------+</span></span><br><span class="line"><span class="operator">|</span> Afghanistan     <span class="operator">|</span> Asia       <span class="operator">|</span> <span class="number">652230</span>     <span class="operator">|</span> <span class="number">25500100</span>     <span class="operator">|</span> <span class="number">20343000</span>      <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> Albania         <span class="operator">|</span> Europe     <span class="operator">|</span> <span class="number">28748</span>      <span class="operator">|</span> <span class="number">2831741</span>      <span class="operator">|</span> <span class="number">12960000</span>      <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> Algeria         <span class="operator">|</span> Africa     <span class="operator">|</span> <span class="number">2381741</span>    <span class="operator">|</span> <span class="number">37100000</span>     <span class="operator">|</span> <span class="number">188681000</span>     <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> Andorra         <span class="operator">|</span> Europe     <span class="operator">|</span> <span class="number">468</span>        <span class="operator">|</span> <span class="number">78115</span>        <span class="operator">|</span> <span class="number">3712000</span>       <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> Angola          <span class="operator">|</span> Africa     <span class="operator">|</span> <span class="number">1246700</span>    <span class="operator">|</span> <span class="number">20609294</span>     <span class="operator">|</span> <span class="number">100990000</span>     <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">-----------------+------------+------------+--------------+---------------+</span></span><br></pre></td></tr></table></figure><p>查找面积超过 3,000,000 或者人口数超过 25,000,000 的国家。效果如下</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">--------------+-------------+--------------+</span></span><br><span class="line"><span class="operator">|</span> name         <span class="operator">|</span> population  <span class="operator">|</span> area         <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">--------------+-------------+--------------+</span></span><br><span class="line"><span class="operator">|</span> Afghanistan  <span class="operator">|</span> <span class="number">25500100</span>    <span class="operator">|</span> <span class="number">652230</span>       <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> Algeria      <span class="operator">|</span> <span class="number">37100000</span>    <span class="operator">|</span> <span class="number">2381741</span>      <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">--------------+-------------+--------------+</span></span><br></pre></td></tr></table></figure><div class="hide-block"><button type="button" class="hide-button" style="">查看答案    </button><div class="hide-content"><p>解：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> name,</span><br><span class="line">    population,</span><br><span class="line">    area</span><br><span class="line"><span class="keyword">FROM</span></span><br><span class="line">    World</span><br><span class="line"><span class="keyword">WHERE</span></span><br><span class="line">    area <span class="operator">&gt;</span> <span class="number">3000000</span></span><br><span class="line">    <span class="keyword">OR</span> population <span class="operator">&gt;</span> <span class="number">25000000</span>;</span><br></pre></td></tr></table></figure></div></div><h2 id="Swap-Salary"><a href="#Swap-Salary" class="headerlink" title="Swap Salary"></a>Swap Salary</h2><p>原题：<a href="https://leetcode.com/problems/swap-salary/description/">https://leetcode.com/problems/swap-salary/description/</a></p><p>创建表结构</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span></span><br><span class="line">IF</span><br><span class="line">    <span class="keyword">EXISTS</span> salary;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> salary ( id <span class="type">INT</span>, NAME <span class="type">VARCHAR</span> ( <span class="number">100</span> ), sex <span class="type">CHAR</span> ( <span class="number">1</span> ), salary <span class="type">INT</span> );</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> salary ( id, NAME, sex, salary )</span><br><span class="line"><span class="keyword">VALUES</span></span><br><span class="line">    ( <span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;m&#x27;</span>, <span class="string">&#x27;2500&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;f&#x27;</span>, <span class="string">&#x27;1500&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;3&#x27;</span>, <span class="string">&#x27;C&#x27;</span>, <span class="string">&#x27;m&#x27;</span>, <span class="string">&#x27;5500&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;4&#x27;</span>, <span class="string">&#x27;D&#x27;</span>, <span class="string">&#x27;f&#x27;</span>, <span class="string">&#x27;500&#x27;</span> );</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">|</span> id <span class="operator">|</span> name <span class="operator">|</span> sex <span class="operator">|</span> salary <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span><span class="comment">----|------|-----|--------|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">1</span>  <span class="operator">|</span> A    <span class="operator">|</span> m   <span class="operator">|</span> <span class="number">2500</span>   <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">2</span>  <span class="operator">|</span> B    <span class="operator">|</span> f   <span class="operator">|</span> <span class="number">1500</span>   <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">3</span>  <span class="operator">|</span> C    <span class="operator">|</span> m   <span class="operator">|</span> <span class="number">5500</span>   <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">4</span>  <span class="operator">|</span> D    <span class="operator">|</span> f   <span class="operator">|</span> <span class="number">500</span>    <span class="operator">|</span></span><br></pre></td></tr></table></figure><p>Swap Salary</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">|</span> id <span class="operator">|</span> name <span class="operator">|</span> sex <span class="operator">|</span> salary <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span><span class="comment">----|------|-----|--------|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">1</span>  <span class="operator">|</span> A    <span class="operator">|</span> f   <span class="operator">|</span> <span class="number">2500</span>   <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">2</span>  <span class="operator">|</span> B    <span class="operator">|</span> m   <span class="operator">|</span> <span class="number">1500</span>   <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">3</span>  <span class="operator">|</span> C    <span class="operator">|</span> f   <span class="operator">|</span> <span class="number">5500</span>   <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">4</span>  <span class="operator">|</span> D    <span class="operator">|</span> m   <span class="operator">|</span> <span class="number">500</span>    <span class="operator">|</span></span><br></pre></td></tr></table></figure><div class="hide-block"><button type="button" class="hide-button" style="">提示    </button><div class="hide-content"><p>两个相等的数异或的结果为 0，而 0 与任何一个数异或的结果为这个数。</p><p><code>sex</code> 字段只有两个取值：f 和 m，并且有以下规律：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&#x27;f&#x27;</span> <span class="operator">^</span> (<span class="string">&#x27;m&#x27;</span> <span class="operator">^</span> <span class="string">&#x27;f&#x27;</span>) <span class="operator">=</span> <span class="string">&#x27;m&#x27;</span> <span class="operator">^</span> (<span class="string">&#x27;f&#x27;</span> <span class="operator">^</span> <span class="string">&#x27;f&#x27;</span>) <span class="operator">=</span> <span class="string">&#x27;m&#x27;</span></span><br><span class="line"><span class="string">&#x27;m&#x27;</span> <span class="operator">^</span> (<span class="string">&#x27;m&#x27;</span> <span class="operator">^</span> <span class="string">&#x27;f&#x27;</span>) <span class="operator">=</span> <span class="string">&#x27;f&#x27;</span> <span class="operator">^</span> (<span class="string">&#x27;m&#x27;</span> <span class="operator">^</span> <span class="string">&#x27;m&#x27;</span>) <span class="operator">=</span> <span class="string">&#x27;f&#x27;</span></span><br></pre></td></tr></table></figure><p>因此将 <code>sex</code> 字段和 m ^ f 进行异或操作，最后就能反转 <code>sex</code> 字段。</p></div></div><div class="hide-block"><button type="button" class="hide-button" style="">查看答案    </button><div class="hide-content"><p>解：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">UPDATE</span> salary</span><br><span class="line"><span class="keyword">SET</span> sex <span class="operator">=</span> <span class="type">CHAR</span> ( ASCII(sex) <span class="operator">^</span> ASCII( <span class="string">&#x27;m&#x27;</span> ) <span class="operator">^</span> ASCII( <span class="string">&#x27;f&#x27;</span> ) );</span><br></pre></td></tr></table></figure></div></div><h2 id="Not-Boring-Movies"><a href="#Not-Boring-Movies" class="headerlink" title="Not Boring Movies"></a>Not Boring Movies</h2><p>原题：<a href="https://leetcode.com/problems/not-boring-movies/description/">https://leetcode.com/problems/not-boring-movies/description/</a></p><p>创建表结构</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span></span><br><span class="line">IF</span><br><span class="line">    <span class="keyword">EXISTS</span> cinema;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> cinema ( id <span class="type">INT</span>, movie <span class="type">VARCHAR</span> ( <span class="number">255</span> ), description <span class="type">VARCHAR</span> ( <span class="number">255</span> ), rating <span class="type">FLOAT</span> ( <span class="number">2</span>, <span class="number">1</span> ) );</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> cinema ( id, movie, description, rating )</span><br><span class="line"><span class="keyword">VALUES</span></span><br><span class="line">    ( <span class="number">1</span>, <span class="string">&#x27;War&#x27;</span>, <span class="string">&#x27;great 3D&#x27;</span>, <span class="number">8.9</span> ),</span><br><span class="line">    ( <span class="number">2</span>, <span class="string">&#x27;Science&#x27;</span>, <span class="string">&#x27;fiction&#x27;</span>, <span class="number">8.5</span> ),</span><br><span class="line">    ( <span class="number">3</span>, <span class="string">&#x27;irish&#x27;</span>, <span class="string">&#x27;boring&#x27;</span>, <span class="number">6.2</span> ),</span><br><span class="line">    ( <span class="number">4</span>, <span class="string">&#x27;Ice song&#x27;</span>, <span class="string">&#x27;Fantacy&#x27;</span>, <span class="number">8.6</span> ),</span><br><span class="line">    ( <span class="number">5</span>, <span class="string">&#x27;House card&#x27;</span>, <span class="string">&#x27;Interesting&#x27;</span>, <span class="number">9.1</span> );</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">---------+-----------+--------------+-----------+</span></span><br><span class="line"><span class="operator">|</span>   id    <span class="operator">|</span> movie     <span class="operator">|</span>  description <span class="operator">|</span>  rating   <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">---------+-----------+--------------+-----------+</span></span><br><span class="line"><span class="operator">|</span>   <span class="number">1</span>     <span class="operator">|</span> War       <span class="operator">|</span>   great <span class="number">3</span>D   <span class="operator">|</span>   <span class="number">8.9</span>     <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span>   <span class="number">2</span>     <span class="operator">|</span> Science   <span class="operator">|</span>   fiction    <span class="operator">|</span>   <span class="number">8.5</span>     <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span>   <span class="number">3</span>     <span class="operator">|</span> irish     <span class="operator">|</span>   boring     <span class="operator">|</span>   <span class="number">6.2</span>     <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span>   <span class="number">4</span>     <span class="operator">|</span> Ice song  <span class="operator">|</span>   Fantacy    <span class="operator">|</span>   <span class="number">8.6</span>     <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span>   <span class="number">5</span>     <span class="operator">|</span> House card<span class="operator">|</span>   Interesting<span class="operator">|</span>   <span class="number">9.1</span>     <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">---------+-----------+--------------+-----------+</span></span><br></pre></td></tr></table></figure><p>查找 id 为奇数，并且 description 不是 boring 的电影，按 rating 降序。效果如下</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">---------+-----------+--------------+-----------+</span></span><br><span class="line"><span class="operator">|</span>   id    <span class="operator">|</span> movie     <span class="operator">|</span>  description <span class="operator">|</span>  rating   <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">---------+-----------+--------------+-----------+</span></span><br><span class="line"><span class="operator">|</span>   <span class="number">5</span>     <span class="operator">|</span> House card<span class="operator">|</span>   Interesting<span class="operator">|</span>   <span class="number">9.1</span>     <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span>   <span class="number">1</span>     <span class="operator">|</span> War       <span class="operator">|</span>   great <span class="number">3</span>D   <span class="operator">|</span>   <span class="number">8.9</span>     <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">---------+-----------+--------------+-----------+</span></span><br></pre></td></tr></table></figure><div class="hide-block"><button type="button" class="hide-button" style="">查看答案    </button><div class="hide-content"><p>解：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span></span><br><span class="line">    <span class="operator">*</span></span><br><span class="line"><span class="keyword">FROM</span></span><br><span class="line">    cinema</span><br><span class="line"><span class="keyword">WHERE</span></span><br><span class="line">    id <span class="operator">%</span> <span class="number">2</span> <span class="operator">=</span> <span class="number">1</span></span><br><span class="line">    <span class="keyword">AND</span> description <span class="operator">!=</span> <span class="string">&#x27;boring&#x27;</span></span><br><span class="line"><span class="keyword">ORDER</span> <span class="keyword">BY</span></span><br><span class="line">    rating <span class="keyword">DESC</span>;</span><br></pre></td></tr></table></figure></div></div><h2 id="Classes-More-Than-5-Students"><a href="#Classes-More-Than-5-Students" class="headerlink" title="Classes More Than 5 Students"></a>Classes More Than 5 Students</h2><p>原题：<a href="https://leetcode.com/problems/classes-more-than-5-students/description/">https://leetcode.com/problems/classes-more-than-5-students/description/</a></p><p>创建表结构</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span></span><br><span class="line">IF</span><br><span class="line">    <span class="keyword">EXISTS</span> courses;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> courses ( student <span class="type">VARCHAR</span> ( <span class="number">255</span> ), class <span class="type">VARCHAR</span> ( <span class="number">255</span> ) );</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> courses ( student, class )</span><br><span class="line"><span class="keyword">VALUES</span></span><br><span class="line">    ( <span class="string">&#x27;A&#x27;</span>, <span class="string">&#x27;Math&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;B&#x27;</span>, <span class="string">&#x27;English&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;C&#x27;</span>, <span class="string">&#x27;Math&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;D&#x27;</span>, <span class="string">&#x27;Biology&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;E&#x27;</span>, <span class="string">&#x27;Math&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;F&#x27;</span>, <span class="string">&#x27;Computer&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;G&#x27;</span>, <span class="string">&#x27;Math&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;H&#x27;</span>, <span class="string">&#x27;Math&#x27;</span> ),</span><br><span class="line">    ( <span class="string">&#x27;I&#x27;</span>, <span class="string">&#x27;Math&#x27;</span> );</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">---------+------------+</span></span><br><span class="line"><span class="operator">|</span> student <span class="operator">|</span> class      <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">---------+------------+</span></span><br><span class="line"><span class="operator">|</span> A       <span class="operator">|</span> Math       <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> B       <span class="operator">|</span> English    <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> C       <span class="operator">|</span> Math       <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> D       <span class="operator">|</span> Biology    <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> E       <span class="operator">|</span> Math       <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> F       <span class="operator">|</span> Computer   <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> G       <span class="operator">|</span> Math       <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> H       <span class="operator">|</span> Math       <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> I       <span class="operator">|</span> Math       <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">---------+------------+</span></span><br></pre></td></tr></table></figure><p>查找有五名及以上 student 的 class。效果如下</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">---------+</span></span><br><span class="line"><span class="operator">|</span> class   <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">---------+</span></span><br><span class="line"><span class="operator">|</span> Math    <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">---------+</span></span><br></pre></td></tr></table></figure><div class="hide-block"><button type="button" class="hide-button" style="">提示    </button><div class="hide-content"><p>对 class 列进行分组之后，再使用 count 汇总函数统计每个分组的记录个数，之后使用 HAVING 进行筛选。HAVING 针对分组进行筛选，而 WHERE 针对每个记录（行）进行筛选。</p></div></div><div class="hide-block"><button type="button" class="hide-button" style="">查看答案    </button><div class="hide-content"><p>解：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span></span><br><span class="line">    class</span><br><span class="line"><span class="keyword">FROM</span></span><br><span class="line">    courses</span><br><span class="line"><span class="keyword">GROUP</span> <span class="keyword">BY</span></span><br><span class="line">    class</span><br><span class="line"><span class="keyword">HAVING</span></span><br><span class="line">    <span class="built_in">count</span>( <span class="keyword">DISTINCT</span> student ) <span class="operator">&gt;=</span> <span class="number">5</span>;</span><br></pre></td></tr></table></figure></div></div><h2 id="Duplicate-Emails"><a href="#Duplicate-Emails" class="headerlink" title="Duplicate Emails"></a>Duplicate Emails</h2><p>原题：<a href="https://leetcode.com/problems/duplicate-emails/description/">https://leetcode.com/problems/duplicate-emails/description/</a></p><p>创建表结构</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span></span><br><span class="line">IF</span><br><span class="line">    <span class="keyword">EXISTS</span> Person;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> Person ( Id <span class="type">INT</span>, Email <span class="type">VARCHAR</span> ( <span class="number">255</span> ) );</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> Person ( Id, Email )</span><br><span class="line"><span class="keyword">VALUES</span></span><br><span class="line">    ( <span class="number">1</span>, <span class="string">&#x27;a@b.com&#x27;</span> ),</span><br><span class="line">    ( <span class="number">2</span>, <span class="string">&#x27;c@d.com&#x27;</span> ),</span><br><span class="line">    ( <span class="number">3</span>, <span class="string">&#x27;a@b.com&#x27;</span> );</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">----+---------+</span></span><br><span class="line"><span class="operator">|</span> Id <span class="operator">|</span> Email   <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+---------+</span></span><br><span class="line"><span class="operator">|</span> <span class="number">1</span>  <span class="operator">|</span> a<span class="variable">@b</span>.com <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">2</span>  <span class="operator">|</span> c<span class="variable">@d</span>.com <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">3</span>  <span class="operator">|</span> a<span class="variable">@b</span>.com <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+---------+</span></span><br></pre></td></tr></table></figure><p>查找重复的邮件地址，效果如下</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">---------+</span></span><br><span class="line"><span class="operator">|</span> Email   <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">---------+</span></span><br><span class="line"><span class="operator">|</span> a<span class="variable">@b</span>.com <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">---------+</span></span><br></pre></td></tr></table></figure><div class="hide-block"><button type="button" class="hide-button" style="">提示    </button><div class="hide-content"><p>对 Email 进行分组并使用 COUNT 进行计数统计，结果大于等于 2 的表示 Email 重复。</p></div></div><div class="hide-block"><button type="button" class="hide-button" style="">查看答案    </button><div class="hide-content"><p>解：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span></span><br><span class="line">    Email</span><br><span class="line"><span class="keyword">FROM</span></span><br><span class="line">    Person</span><br><span class="line"><span class="keyword">GROUP</span> <span class="keyword">BY</span></span><br><span class="line">    Email</span><br><span class="line"><span class="keyword">HAVING</span></span><br><span class="line">    <span class="built_in">COUNT</span>( <span class="operator">*</span> ) <span class="operator">&gt;=</span> <span class="number">2</span>;</span><br></pre></td></tr></table></figure></div></div><h2 id="Delete-Duplicate-Emails"><a href="#Delete-Duplicate-Emails" class="headerlink" title="Delete Duplicate Emails"></a>Delete Duplicate Emails</h2><p>原题：<a href="https://leetcode.com/problems/delete-duplicate-emails/description/">https://leetcode.com/problems/delete-duplicate-emails/description/</a></p><p>创建表结构，同上题</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">----+---------+</span></span><br><span class="line"><span class="operator">|</span> Id <span class="operator">|</span> Email   <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+---------+</span></span><br><span class="line"><span class="operator">|</span> <span class="number">1</span>  <span class="operator">|</span> john<span class="variable">@example</span>.com <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">2</span>  <span class="operator">|</span> bob<span class="variable">@example</span>.com <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">3</span>  <span class="operator">|</span> john<span class="variable">@example</span>.com <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+---------+</span></span><br></pre></td></tr></table></figure><p>删除重复的邮件地址：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">----+------------------+</span></span><br><span class="line"><span class="operator">|</span> Id <span class="operator">|</span> Email            <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+------------------+</span></span><br><span class="line"><span class="operator">|</span> <span class="number">1</span>  <span class="operator">|</span> john<span class="variable">@example</span>.com <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">2</span>  <span class="operator">|</span> bob<span class="variable">@example</span>.com  <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+------------------+</span></span><br></pre></td></tr></table></figure><div class="hide-block"><button type="button" class="hide-button" style="">提示    </button><div class="hide-content"><p>只保留相同 Email 中 Id 最小的那一个，然后删除其它的。</p></div></div><div class="hide-block"><button type="button" class="hide-button" style="">查看答案    </button><div class="hide-content"><p>解：</p><div class="tabs" id="test4"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="test4-1">方法一：连接查询</button><button type="button" class="tab " data-href="test4-2">方法二：子查询</button></ul><div class="tab-contents"><div class="tab-item-content active" id="test4-1"><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span></span><br><span class="line">    Email</span><br><span class="line"><span class="keyword">FROM</span></span><br><span class="line">    Person</span><br><span class="line"><span class="keyword">GROUP</span> <span class="keyword">BY</span></span><br><span class="line">    Email</span><br><span class="line"><span class="keyword">HAVING</span></span><br><span class="line">    <span class="built_in">COUNT</span>( <span class="operator">*</span> ) <span class="operator">&gt;=</span> <span class="number">2</span>;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="test4-2"><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DELETE</span></span><br><span class="line"><span class="keyword">FROM</span></span><br><span class="line">    Person</span><br><span class="line"><span class="keyword">WHERE</span></span><br><span class="line">    id <span class="keyword">NOT</span> <span class="keyword">IN</span> (</span><br><span class="line">        <span class="keyword">SELECT</span> id </span><br><span class="line">        <span class="keyword">FROM</span> ( </span><br><span class="line">            <span class="keyword">SELECT</span> <span class="built_in">min</span>( id ) <span class="keyword">AS</span> id </span><br><span class="line">            <span class="keyword">FROM</span> Person</span><br><span class="line">            <span class="keyword">GROUP</span> <span class="keyword">BY</span> email</span><br><span class="line">        ) <span class="keyword">AS</span> m</span><br><span class="line">    );</span><br></pre></td></tr></table></figure><div class="note warning flat"><p>应该注意的是上述解法额外嵌套了一个 SELECT 语句，如果不这么做，会出现错误：You can’t specify target table ‘Person’ for update in FROM clause。以下演示了这种错误解法。</p></div><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DELETE</span></span><br><span class="line"><span class="keyword">FROM</span></span><br><span class="line">    Person</span><br><span class="line"><span class="keyword">WHERE</span></span><br><span class="line">    id <span class="keyword">NOT</span> <span class="keyword">IN</span> ( </span><br><span class="line">        <span class="keyword">SELECT</span> <span class="built_in">min</span>( id ) <span class="keyword">AS</span> id </span><br><span class="line">        <span class="keyword">FROM</span> Person </span><br><span class="line">        <span class="keyword">GROUP</span> <span class="keyword">BY</span> email </span><br><span class="line">    );</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div></div><h2 id="Combine-Two-Tables"><a href="#Combine-Two-Tables" class="headerlink" title="Combine Two Tables"></a>Combine Two Tables</h2><p>原题：<a href="https://leetcode.com/problems/combine-two-tables/description/">https://leetcode.com/problems/combine-two-tables/description/</a></p><p>创建表结构</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span></span><br><span class="line">IF</span><br><span class="line">    <span class="keyword">EXISTS</span> Person;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> Person ( PersonId <span class="type">INT</span>, FirstName <span class="type">VARCHAR</span> ( <span class="number">255</span> ), LastName <span class="type">VARCHAR</span> ( <span class="number">255</span> ) );</span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span></span><br><span class="line">IF</span><br><span class="line">    <span class="keyword">EXISTS</span> Address;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> Address ( AddressId <span class="type">INT</span>, PersonId <span class="type">INT</span>, City <span class="type">VARCHAR</span> ( <span class="number">255</span> ), State <span class="type">VARCHAR</span> ( <span class="number">255</span> ) );</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> Person ( PersonId, LastName, FirstName )</span><br><span class="line"><span class="keyword">VALUES</span></span><br><span class="line">    ( <span class="number">1</span>, <span class="string">&#x27;Wang&#x27;</span>, <span class="string">&#x27;Allen&#x27;</span> );</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> Address ( AddressId, PersonId, City, State )</span><br><span class="line"><span class="keyword">VALUES</span></span><br><span class="line">    ( <span class="number">1</span>, <span class="number">2</span>, <span class="string">&#x27;New York City&#x27;</span>, <span class="string">&#x27;New York&#x27;</span> );</span><br></pre></td></tr></table></figure><p><strong>Person表：</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">-------------+---------+</span></span><br><span class="line"><span class="operator">|</span> <span class="keyword">Column</span> Name <span class="operator">|</span> Type    <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">-------------+---------+</span></span><br><span class="line"><span class="operator">|</span> PersonId    <span class="operator">|</span> <span class="type">int</span>     <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> FirstName   <span class="operator">|</span> <span class="type">varchar</span> <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> LastName    <span class="operator">|</span> <span class="type">varchar</span> <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">-------------+---------+</span></span><br><span class="line">PersonId <span class="keyword">is</span> the <span class="keyword">primary</span> key <span class="keyword">column</span> <span class="keyword">for</span> this table.</span><br></pre></td></tr></table></figure><p><strong>Address 表：</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">-------------+---------+</span></span><br><span class="line"><span class="operator">|</span> <span class="keyword">Column</span> Name <span class="operator">|</span> Type    <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">-------------+---------+</span></span><br><span class="line"><span class="operator">|</span> AddressId   <span class="operator">|</span> <span class="type">int</span>     <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> PersonId    <span class="operator">|</span> <span class="type">int</span>     <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> City        <span class="operator">|</span> <span class="type">varchar</span> <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> State       <span class="operator">|</span> <span class="type">varchar</span> <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">-------------+---------+</span></span><br><span class="line">AddressId <span class="keyword">is</span> the <span class="keyword">primary</span> key <span class="keyword">column</span> <span class="keyword">for</span> this table.</span><br></pre></td></tr></table></figure><p>查找 FirstName, LastName, City, State 数据，而不管一个用户有没有填地址信息。</p><div class="hide-block"><button type="button" class="hide-button" style="">提示    </button><div class="hide-content"><p>涉及到 Person 和 Address 两个表，在对这两个表执行连接操作时，因为要保留 Person 表中的信息，即使在 Address 表中没有关联的信息也要保留。此时可以用左外连接，将 Person 表放在 <code>LEFT JOIN</code> 的左边。</p></div></div><div class="hide-block"><button type="button" class="hide-button" style="">查看答案    </button><div class="hide-content"><p>解：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span></span><br><span class="line">    FirstName,</span><br><span class="line">    LastName,</span><br><span class="line">    City,</span><br><span class="line">    State</span><br><span class="line"><span class="keyword">FROM</span></span><br><span class="line">    Person P</span><br><span class="line">    <span class="keyword">LEFT</span> <span class="keyword">JOIN</span> Address A</span><br><span class="line">    <span class="keyword">ON</span> P.PersonId <span class="operator">=</span> A.PersonId;</span><br></pre></td></tr></table></figure></div></div><h2 id="Employees-Earning-More-Than-Their-Managers"><a href="#Employees-Earning-More-Than-Their-Managers" class="headerlink" title="Employees Earning More Than Their Managers"></a>Employees Earning More Than Their Managers</h2><p>原题：<a href="https://leetcode.com/problems/employees-earning-more-than-their-managers/description/">https://leetcode.com/problems/employees-earning-more-than-their-managers/description/</a></p><p>创建表结构</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span></span><br><span class="line">IF</span><br><span class="line">    <span class="keyword">EXISTS</span> Employee;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> Employee ( Id <span class="type">INT</span>, NAME <span class="type">VARCHAR</span> ( <span class="number">255</span> ), Salary <span class="type">INT</span>, ManagerId <span class="type">INT</span> );</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> Employee ( Id, NAME, Salary, ManagerId )</span><br><span class="line"><span class="keyword">VALUES</span></span><br><span class="line">    ( <span class="number">1</span>, <span class="string">&#x27;Joe&#x27;</span>, <span class="number">70000</span>, <span class="number">3</span> ),</span><br><span class="line">    ( <span class="number">2</span>, <span class="string">&#x27;Henry&#x27;</span>, <span class="number">80000</span>, <span class="number">4</span> ),</span><br><span class="line">    ( <span class="number">3</span>, <span class="string">&#x27;Sam&#x27;</span>, <span class="number">60000</span>, <span class="keyword">NULL</span> ),</span><br><span class="line">    ( <span class="number">4</span>, <span class="string">&#x27;Max&#x27;</span>, <span class="number">90000</span>, <span class="keyword">NULL</span> );</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">----+-------+--------+-----------+</span></span><br><span class="line"><span class="operator">|</span> Id <span class="operator">|</span> Name  <span class="operator">|</span> Salary <span class="operator">|</span> ManagerId <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+-------+--------+-----------+</span></span><br><span class="line"><span class="operator">|</span> <span class="number">1</span>  <span class="operator">|</span> Joe   <span class="operator">|</span> <span class="number">70000</span>  <span class="operator">|</span> <span class="number">3</span>         <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">2</span>  <span class="operator">|</span> Henry <span class="operator">|</span> <span class="number">80000</span>  <span class="operator">|</span> <span class="number">4</span>         <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">3</span>  <span class="operator">|</span> Sam   <span class="operator">|</span> <span class="number">60000</span>  <span class="operator">|</span> <span class="keyword">NULL</span>      <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">4</span>  <span class="operator">|</span> Max   <span class="operator">|</span> <span class="number">90000</span>  <span class="operator">|</span> <span class="keyword">NULL</span>      <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+-------+--------+-----------+</span></span><br></pre></td></tr></table></figure><p>查找薪资大于其经理薪资的员工信息。</p><div class="hide-block"><button type="button" class="hide-button" style="">查看答案    </button><div class="hide-content"><p>解：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span></span><br><span class="line">    E1.NAME <span class="keyword">AS</span> Employee</span><br><span class="line"><span class="keyword">FROM</span></span><br><span class="line">    Employee E1</span><br><span class="line">    <span class="keyword">INNER</span> <span class="keyword">JOIN</span> Employee E2</span><br><span class="line">    <span class="keyword">ON</span> E1.ManagerId <span class="operator">=</span> E2.Id</span><br><span class="line">    <span class="keyword">AND</span> E1.Salary <span class="operator">&gt;</span> E2.Salary;</span><br></pre></td></tr></table></figure></div></div><h2 id="Customers-Who-Never-Order"><a href="#Customers-Who-Never-Order" class="headerlink" title="Customers Who Never Order"></a>Customers Who Never Order</h2><p>原题：<a href="https://leetcode.com/problems/customers-who-never-order/description/">https://leetcode.com/problems/customers-who-never-order/description/</a></p><p>创建表结构</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span></span><br><span class="line">IF</span><br><span class="line">    <span class="keyword">EXISTS</span> Customers;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> Customers ( Id <span class="type">INT</span>, NAME <span class="type">VARCHAR</span> ( <span class="number">255</span> ) );</span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span></span><br><span class="line">IF</span><br><span class="line">    <span class="keyword">EXISTS</span> Orders;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> Orders ( Id <span class="type">INT</span>, CustomerId <span class="type">INT</span> );</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> Customers ( Id, NAME )</span><br><span class="line"><span class="keyword">VALUES</span></span><br><span class="line">    ( <span class="number">1</span>, <span class="string">&#x27;Joe&#x27;</span> ),</span><br><span class="line">    ( <span class="number">2</span>, <span class="string">&#x27;Henry&#x27;</span> ),</span><br><span class="line">    ( <span class="number">3</span>, <span class="string">&#x27;Sam&#x27;</span> ),</span><br><span class="line">    ( <span class="number">4</span>, <span class="string">&#x27;Max&#x27;</span> );</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> Orders ( Id, CustomerId )</span><br><span class="line"><span class="keyword">VALUES</span></span><br><span class="line">    ( <span class="number">1</span>, <span class="number">3</span> ),</span><br><span class="line">    ( <span class="number">2</span>, <span class="number">1</span> );</span><br></pre></td></tr></table></figure><p><strong>Customers 表：</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">----+-------+</span></span><br><span class="line"><span class="operator">|</span> Id <span class="operator">|</span> Name  <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+-------+</span></span><br><span class="line"><span class="operator">|</span> <span class="number">1</span>  <span class="operator">|</span> Joe   <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">2</span>  <span class="operator">|</span> Henry <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">3</span>  <span class="operator">|</span> Sam   <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">4</span>  <span class="operator">|</span> Max   <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+-------+</span></span><br></pre></td></tr></table></figure><p><strong>Orders 表：</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">----+------------+</span></span><br><span class="line"><span class="operator">|</span> Id <span class="operator">|</span> CustomerId <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+------------+</span></span><br><span class="line"><span class="operator">|</span> <span class="number">1</span>  <span class="operator">|</span> <span class="number">3</span>          <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">2</span>  <span class="operator">|</span> <span class="number">1</span>          <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+------------+</span></span><br></pre></td></tr></table></figure><p>查找没有订单的顾客信息：如下</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">-----------+</span></span><br><span class="line"><span class="operator">|</span> Customers <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">-----------+</span></span><br><span class="line"><span class="operator">|</span> Henry     <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> Max       <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">-----------+</span></span><br></pre></td></tr></table></figure><div class="hide-block"><button type="button" class="hide-button" style="">查看答案    </button><div class="hide-content"><p>解：</p><div class="tabs" id="test4"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="test4-1">方法一：左外链接</button><button type="button" class="tab " data-href="test4-2">方法二：子查询</button></ul><div class="tab-contents"><div class="tab-item-content active" id="test4-1"><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span></span><br><span class="line">    C.Name <span class="keyword">AS</span> Customers</span><br><span class="line"><span class="keyword">FROM</span></span><br><span class="line">    Customers C</span><br><span class="line">    <span class="keyword">LEFT</span> <span class="keyword">JOIN</span> Orders O</span><br><span class="line">    <span class="keyword">ON</span> C.Id <span class="operator">=</span> O.CustomerId</span><br><span class="line"><span class="keyword">WHERE</span></span><br><span class="line">    O.CustomerId <span class="keyword">IS</span> <span class="keyword">NULL</span>;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="test4-2"><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span></span><br><span class="line">    Name <span class="keyword">AS</span> Customers</span><br><span class="line"><span class="keyword">FROM</span></span><br><span class="line">    Customers</span><br><span class="line"><span class="keyword">WHERE</span></span><br><span class="line">    Id <span class="keyword">NOT</span> <span class="keyword">IN</span> ( </span><br><span class="line">        <span class="keyword">SELECT</span> CustomerId </span><br><span class="line">        <span class="keyword">FROM</span> Orders </span><br><span class="line">    );</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div></div><h2 id="Department-Highest-Salary"><a href="#Department-Highest-Salary" class="headerlink" title="Department Highest Salary"></a>Department Highest Salary</h2><p>原题：<a href="https://leetcode.com/problems/department-highest-salary/description/">https://leetcode.com/problems/department-highest-salary/description/</a></p><p>创建表结构</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> IF <span class="keyword">EXISTS</span> Employee;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> Employee ( Id <span class="type">INT</span>, NAME <span class="type">VARCHAR</span> ( <span class="number">255</span> ), Salary <span class="type">INT</span>, DepartmentId <span class="type">INT</span> );</span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> IF <span class="keyword">EXISTS</span> Department;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> Department ( Id <span class="type">INT</span>, NAME <span class="type">VARCHAR</span> ( <span class="number">255</span> ) );</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> Employee ( Id, NAME, Salary, DepartmentId )</span><br><span class="line"><span class="keyword">VALUES</span></span><br><span class="line">    ( <span class="number">1</span>, <span class="string">&#x27;Joe&#x27;</span>, <span class="number">70000</span>, <span class="number">1</span> ),</span><br><span class="line">    ( <span class="number">2</span>, <span class="string">&#x27;Henry&#x27;</span>, <span class="number">80000</span>, <span class="number">2</span> ),</span><br><span class="line">    ( <span class="number">3</span>, <span class="string">&#x27;Sam&#x27;</span>, <span class="number">60000</span>, <span class="number">2</span> ),</span><br><span class="line">    ( <span class="number">4</span>, <span class="string">&#x27;Max&#x27;</span>, <span class="number">90000</span>, <span class="number">1</span> );</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> Department ( Id, NAME )</span><br><span class="line"><span class="keyword">VALUES</span></span><br><span class="line">    ( <span class="number">1</span>, <span class="string">&#x27;IT&#x27;</span> ),</span><br><span class="line">    ( <span class="number">2</span>, <span class="string">&#x27;Sales&#x27;</span> );</span><br></pre></td></tr></table></figure><p><strong>Employee 表：</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">----+-------+--------+--------------+</span></span><br><span class="line"><span class="operator">|</span> Id <span class="operator">|</span> Name  <span class="operator">|</span> Salary <span class="operator">|</span> DepartmentId <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+-------+--------+--------------+</span></span><br><span class="line"><span class="operator">|</span> <span class="number">1</span>  <span class="operator">|</span> Joe   <span class="operator">|</span> <span class="number">70000</span>  <span class="operator">|</span> <span class="number">1</span>            <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">2</span>  <span class="operator">|</span> Henry <span class="operator">|</span> <span class="number">80000</span>  <span class="operator">|</span> <span class="number">2</span>            <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">3</span>  <span class="operator">|</span> Sam   <span class="operator">|</span> <span class="number">60000</span>  <span class="operator">|</span> <span class="number">2</span>            <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">4</span>  <span class="operator">|</span> Max   <span class="operator">|</span> <span class="number">90000</span>  <span class="operator">|</span> <span class="number">1</span>            <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+-------+--------+--------------+</span></span><br></pre></td></tr></table></figure><p><strong>Department 表：</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">----+----------+</span></span><br><span class="line"><span class="operator">|</span> Id <span class="operator">|</span> Name     <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+----------+</span></span><br><span class="line"><span class="operator">|</span> <span class="number">1</span>  <span class="operator">|</span> IT       <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">2</span>  <span class="operator">|</span> Sales    <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+----------+</span></span><br></pre></td></tr></table></figure><p>查找一个 Department 中收入最高者的信息，如下</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">------------+----------+--------+</span></span><br><span class="line"><span class="operator">|</span> Department <span class="operator">|</span> Employee <span class="operator">|</span> Salary <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">------------+----------+--------+</span></span><br><span class="line"><span class="operator">|</span> IT         <span class="operator">|</span> Max      <span class="operator">|</span> <span class="number">90000</span>  <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> Sales      <span class="operator">|</span> Henry    <span class="operator">|</span> <span class="number">80000</span>  <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">------------+----------+--------+</span></span><br></pre></td></tr></table></figure><div class="hide-block"><button type="button" class="hide-button" style="">提示    </button><div class="hide-content"><p>创建一个临时表，包含了部门员工的最大薪资。可以对部门进行分组，然后使用 MAX() 汇总函数取得最大薪资。</p><p>之后使用连接找到一个部门中薪资等于临时表中最大薪资的员工。</p></div></div><div class="hide-block"><button type="button" class="hide-button" style="">查看答案    </button><div class="hide-content"><p>解：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span></span><br><span class="line">    D.NAME Department,</span><br><span class="line">    E.NAME Employee,</span><br><span class="line">    E.Salary</span><br><span class="line"><span class="keyword">FROM</span></span><br><span class="line">    Employee E,</span><br><span class="line">    Department D,</span><br><span class="line">    ( <span class="keyword">SELECT</span> DepartmentId, <span class="built_in">MAX</span>( Salary ) Salary </span><br><span class="line">     <span class="keyword">FROM</span> Employee </span><br><span class="line">     <span class="keyword">GROUP</span> <span class="keyword">BY</span> DepartmentId ) M</span><br><span class="line"><span class="keyword">WHERE</span></span><br><span class="line">    E.DepartmentId <span class="operator">=</span> D.Id</span><br><span class="line">    <span class="keyword">AND</span> E.DepartmentId <span class="operator">=</span> M.DepartmentId</span><br><span class="line">    <span class="keyword">AND</span> E.Salary <span class="operator">=</span> M.Salary;</span><br></pre></td></tr></table></figure></div></div><h2 id="Second-Highest-Salary"><a href="#Second-Highest-Salary" class="headerlink" title="Second Highest Salary"></a>Second Highest Salary</h2><p><a href="https://leetcode.com/problems/second-highest-salary/description/">https://leetcode.com/problems/second-highest-salary/description/</a></p><p>创建表结构</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span></span><br><span class="line">IF</span><br><span class="line">    <span class="keyword">EXISTS</span> Employee;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> Employee ( Id <span class="type">INT</span>, Salary <span class="type">INT</span> );</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> Employee ( Id, Salary )</span><br><span class="line"><span class="keyword">VALUES</span></span><br><span class="line">    ( <span class="number">1</span>, <span class="number">100</span> ),</span><br><span class="line">    ( <span class="number">2</span>, <span class="number">200</span> ),</span><br><span class="line">    ( <span class="number">3</span>, <span class="number">300</span> );</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">----+--------+</span></span><br><span class="line"><span class="operator">|</span> Id <span class="operator">|</span> Salary <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+--------+</span></span><br><span class="line"><span class="operator">|</span> <span class="number">1</span>  <span class="operator">|</span> <span class="number">100</span>    <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">2</span>  <span class="operator">|</span> <span class="number">200</span>    <span class="operator">|</span></span><br><span class="line"><span class="operator">|</span> <span class="number">3</span>  <span class="operator">|</span> <span class="number">300</span>    <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">----+--------+</span></span><br></pre></td></tr></table></figure><p>查找工资第二高的员工。如下</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="operator">+</span><span class="comment">---------------------+</span></span><br><span class="line"><span class="operator">|</span> SecondHighestSalary <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">---------------------+</span></span><br><span class="line"><span class="operator">|</span> <span class="number">200</span>                 <span class="operator">|</span></span><br><span class="line"><span class="operator">+</span><span class="comment">---------------------+</span></span><br></pre></td></tr></table></figure><p>没有找到返回 null 而不是不返回数据。</p><div class="hide-block"><button type="button" class="hide-button" style="">提示    </button><div class="hide-content"><p>为了在没有查找到数据时返回 null，需要在查询结果外面再套一层 SELECT。</p></div></div><div class="hide-block"><button type="button" class="hide-button" style="">查看答案    </button><div class="hide-content"><p>解：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span></span><br><span class="line">    ( <span class="keyword">SELECT</span> <span class="keyword">DISTINCT</span> Salary </span><br><span class="line">     <span class="keyword">FROM</span> Employee </span><br><span class="line">     <span class="keyword">ORDER</span> <span class="keyword">BY</span> Salary <span class="keyword">DESC</span> </span><br><span class="line">     LIMIT <span class="number">1</span>, <span class="number">1</span> ) SecondHighestSalary;</span><br></pre></td></tr></table></figure></div></div>]]></content>
    
    
    <summary type="html">Big Countries-查找面积超过 3,000,000 或者人口数超过 25,000,000 的国家。Swap Salary-只用一个 SQL 查询，将 sex 字段反转。Not Boring Movies-查找 id 为奇数，并且 description 不是 boring 的电影，按 rating 降序。</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="MySQL" scheme="https://blog.imzjw.cn/tags/MySQL/"/>
    
  </entry>
  
  <entry>
    <title>Spring Cloud的那些组件</title>
    <link href="https://blog.imzjw.cn/posts/cloud-module/"/>
    <id>https://blog.imzjw.cn/posts/cloud-module/</id>
    <published>2020-12-01T14:30:19.000Z</published>
    <updated>2020-12-01T14:30:19.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>Spring Cloud 啊</p><p>那就得提一下微服务框架，所谓的微服务框架就是把负责的功能拆分成比较小、功能比较单一的服务独立处理，比如单点登录服务、支付服务、订单服务等，当然如果订单功能比较复杂还可以独立出更具体的服务。</p><h2 id="Spring-Cloud-Config"><a href="#Spring-Cloud-Config" class="headerlink" title="Spring Cloud Config"></a>Spring Cloud Config</h2><p>配置中心</p><p>将系统中用到的一些配置信息存储到配置中心，这样就方便维护啦，不用每次修改配置都重启服务。用的比较多的配置中心还有 etcd、携程的 Apollo、Disconf 。</p><p>其实还有 Alibaba 的 Nacos, 但是我还没进一步的去了解 </p><h2 id="Spring-Cloud-Netflix"><a href="#Spring-Cloud-Netflix" class="headerlink" title="Spring Cloud Netflix"></a>Spring Cloud Netflix</h2><p>Netflix OSS 是一组开源的框架和组件库，是 Netflix 公司开发出来解决分布式系统的一些有趣的可扩展类库。Spring Cloud 把他们都放到 Spring Cloud Netflix 下，这是一个框架集合，它包括 Eureka 、Ribbon、Zuul、Hystrix 等。</p><h3 id="Eureka"><a href="#Eureka" class="headerlink" title="Eureka"></a>Eureka</h3><p>服务注册中心</p><p>这可以说是微服务架构的核心功能了，微服务部署之后，一定要有服务注册和发现的能力，而 Eureka 就是担任这个角色的。如果你用过 Dubbo 的话，那一定知道 Dubbo 中服务注册和发现的功能是用 Zookeeper 来实现的。</p><p>目前官方已停止升级，如果你的项目中还没有使用并且打算使用注册中心的话，可以直接使用 Spring Cloud Consul or Spring Cloud Alibaba Nacos</p><h3 id="Ribbon"><a href="#Ribbon" class="headerlink" title="Ribbon"></a>Ribbon</h3><p>服务调用</p><p>提供客户端负载均衡功能，例如一个服务提供者部署了 3 个实例，那么使用 Ribbon 可以指定负载均衡算法去请求其中一个实例，Ribbon 如果配合 Eureka ，使用起来非常简单😊</p><h3 id="Hystrix"><a href="#Hystrix" class="headerlink" title="Hystrix"></a>Hystrix</h3><p>服务熔断器</p><p>假设有 3 个服务提供实例，其中有一个实例由于某中原因挂掉了，那么当再有请求进来的时候，如果还是向这个实例上发送请求的话，那将会导致请求积压阻塞，这个时候，熔断器就要发挥它的作用，将这个有问题的实例下线，这样一来，再有新的请求进来，就不会再发到这个有问题的实例上了。</p><h3 id="Zuul"><a href="#Zuul" class="headerlink" title="Zuul"></a>Zuul</h3><p>服务网关。</p><p>主要实现了路由转发和过滤器功能，对于处理一些数据聚合、鉴权、监控、统计类的功能非常好用。</p><h3 id="Gateway"><a href="#Gateway" class="headerlink" title="Gateway"></a>Gateway</h3><p>它也是服务网关</p><p>可以认为它是 Zuul 的下一代，无论从易用性和性能方便都有所提高，如果你的系统中还没有使用 Zuul，并且准备上网关，可以直接选择 Gateway。</p><h2 id="Spring-Cloud-Consul"><a href="#Spring-Cloud-Consul" class="headerlink" title="Spring Cloud Consul"></a>Spring Cloud Consul</h2><p>Consul 让服务注册和服务发现（通过 DNS 和 HTTP 接口）更加简单，甚至对于外部服务（例如 SaaS）注册也一样。Spring Cloud Consul 可替代已有的 Spring Cloud Eureka。Eureka 2.x 版本也已经停止开发，并且 Spring Cloud 官方也建议用 Spring Cloud Consul 来替代，当然如果已经用了 Eureka 在项目中也没有关系，Eureka 已经足够稳定，正常使用没有任何问题。</p><p>Spring Cloud Consul 可替代已有的 Spring Cloud Config ，当做配置中心使用。</p><h2 id="Spring-Cloud-Stream"><a href="#Spring-Cloud-Stream" class="headerlink" title="Spring Cloud Stream"></a>Spring Cloud Stream</h2><p>Spring Cloud Stream 是消息中间件组件，它集成了 kafka 和 RabbitMQ 。如果你的系统中打算集成 kafka 或 <code>RabbitMQ</code>，可以考虑使用 <code>Stream</code> 。</p><h2 id="Spring-Cloud-Bus"><a href="#Spring-Cloud-Bus" class="headerlink" title="Spring Cloud Bus"></a>Spring Cloud Bus</h2><p>消息总线</p><p>用于在集群（例如，配置变化事件）中传播状态变化，可与 Spring Cloud Config 联合实现热部署。集成了 RabbitMQ 和 kafka 。刚刚上面说到的 Stream 好像也是这个功能。没错，我们可以认为 Bus 是 Stream 的进一步封装，使用更简单。而 Stream 的灵活性更高。</p><h2 id="Spring-Cloud-OpenFeign"><a href="#Spring-Cloud-OpenFeign" class="headerlink" title="Spring Cloud OpenFeign"></a>Spring Cloud OpenFeign</h2><p>Feign 是一种声明式、模板化的HTTP客户端。它可以用注解的方式简化 HTTP 请求，可以快速简单的请求服务提供接口。如果你还在使用 restTemplate 或者其他方式，不妨考虑一下 Feign。</p><h2 id="Spring-Cloud-Sleuth"><a href="#Spring-Cloud-Sleuth" class="headerlink" title="Spring Cloud Sleuth"></a>Spring Cloud Sleuth</h2><p>服务日志收集和链路追踪模块，封装了 Dapper 和 log-based 追踪以及 Zipkin 和 HTrace 操作。与之功能相同的框架还有 skywalking、Pinpoint，另外国内还有美团开源的 CAT，只不过 CAT 属于代码侵入的，需要开发人员在系统中做代码埋点，不过也更加灵活，更加精细。</p><h2 id="Spring-Cloud-Security"><a href="#Spring-Cloud-Security" class="headerlink" title="Spring Cloud Security"></a>Spring Cloud Security</h2><p>可用做授权服务、单点登录等。如果服务需要做权限控制，那除非你自己实现。不然用到最多的就是 Shiro 和 Spring Security 。Spring Boot 中用的比较多的就是 Security，众多授权机制中属于 OAuth2 最为流行。Spring Cloud Security 就是将 Security、OAuth2 做了集成，方便使用。</p><p>除了以上的这些常用功能外，Spring Cloud 还提供了一些其他的模块，具体的可以到 Spring Cloud 官网一看。官网上介绍的更加详细。</p><p>官网：<a href="https://spring.io/projects/spring-cloud">https://spring.io…</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cloud-module/springcloud20201201231950.webp" alt="img"></p>]]></content>
    
    
    <summary type="html">所谓的微服务框架就是把负责的功能拆分成比较小、功能比较单一的服务独立处理，比如单点登录服务、支付服务、订单服务等，当然如果订单功能比较复杂还可以独立出更具体的服务。</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring Cloud" scheme="https://blog.imzjw.cn/tags/Spring-Cloud/"/>
    
  </entry>
  
  <entry>
    <title>git-生成ssh密钥</title>
    <link href="https://blog.imzjw.cn/posts/git-ssh-generate/"/>
    <id>https://blog.imzjw.cn/posts/git-ssh-generate/</id>
    <published>2020-11-21T10:55:07.000Z</published>
    <updated>2020-11-21T10:55:07.000Z</updated>
    
    <content type="html"><![CDATA[<p>如果你点进来，那我就当作你知道 <code>ssh</code> 和 <code>https</code> 的作用以及区别了，这里我就不讲了</p><p>这第一步肯定是检查下自己之前有没有生成，对叭</p><p>然后管你在哪打开 <code>git bash</code></p><p>执行</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls -al ~/.ssh</span><br></pre></td></tr></table></figure><p>如果能进到 <code>.ssh</code> 文件目录下，那就说明你之前生成过了，直接把他删了，相信我，接着看下一步💔</p><p>如果不能进到 <code>.ssh</code> 文件目录下，那就得先检查一下配置</p><p>直接输入以下命令</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git config user.name</span><br><span class="line">git config user.email</span><br></pre></td></tr></table></figure><p>如果控制台啥都没有提示的话就执行以下命令</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git config --global user.name &quot;小嘉太帅了叭&quot;# Github用户名</span><br><span class="line">git config --global user.email &quot;xiaojia@aliyun.com&quot;# GitHub邮箱</span><br></pre></td></tr></table></figure><p>注意：不要盲目的 <code>cv</code> 哦，根据你自己的用户名邮箱配置</p><p>随后直接生成秘钥</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -t rsa -C &quot;xiaojia@aliyun.com&quot;</span><br></pre></td></tr></table></figure><p>好好看，好好记</p><div class="tip success">    <p> -t 就是 type，指定密钥类型，默认是 rsa, 是可以省略的</p></div><div class="tip success">    <p>-C 就是 comment 提供一个新注释，比如邮箱</p></div><p>接着按3个回车</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">Enter file in which to save the key (/root/.ssh/id_rsa): # 这个就是说密钥文件默认存放的位置，按回车就可以了</span><br><span class="line">Created directory &#x27;/root/.ssh&#x27;.</span><br><span class="line">Enter passphrase (empty for no passphrase): # 设置一个密码，我是建议直接按回车不设置</span><br><span class="line">Enter same passphrase again:    # 再输入一遍密码，没设置直接回车</span><br><span class="line">Your identification has been saved in /root/.ssh/id_rsa. # 这个就是生成的私钥</span><br><span class="line">Your public key has been saved in /root/.ssh/id_rsa.pub. # 这个是生成的公钥</span><br><span class="line">The key fingerprint is:</span><br><span class="line">SHA256:K1qy928tkk1FUuzQtlZK+poeS67vIgPvHw9lQ+KNuZ4 root@localhost.localdomain</span><br><span class="line">The key&#x27;s randomart image is:</span><br><span class="line">+---[RSA 2048]----+</span><br><span class="line">|           +.    |</span><br><span class="line">|          o * .  |</span><br><span class="line">|        . .O +   |</span><br><span class="line">|       . *. *    |</span><br><span class="line">|        S =+     |</span><br><span class="line">|    .    =...    |</span><br><span class="line">|    .oo =+o+     |</span><br><span class="line">|     ==o+B*o.    |</span><br><span class="line">|    oo.=EXO.     |</span><br><span class="line">+----[SHA256]-----+</span><br></pre></td></tr></table></figure><p>最后在 <code>.ssh</code> 目录下有两个文件分别是</p><p>id_rsa：私有秘钥     </p><p>id_rsa.pub：公有密钥</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/git-ssh-generate/20201121202801.webp" alt="img"/><p>这不知道第几步了，那就下一步</p><p>如果你想登陆远端的话，那你就需要将 <code>rsa.pub</code> 里的秘钥添加到 github上。</p><p>登录 github，点击你可爱的头像，进入 <code>Settings</code></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/git-ssh-generate/20201121203155.webp" alt="img" width="30%"/><p>进入到 <code>Settings</code> 之后你就会发现一个可爱的大头像，我们点击 <code>SSH and GPG keys</code></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/git-ssh-generate/20201121203412.webp" alt="img" width="80%"/><div class="tip warning">    <p>New SSH key</p></div><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/git-ssh-generate/20201121203619.webp" alt="img" /><p>粘贴你的公钥到 key 输入框中，也就是 rsa.pub</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/git-ssh-generate/20201121203821.webp" alt="img" /><p>来来来，我们来测试一下是否成功</p><p>管你在哪打开 <code>git bash</code></p><p>输入 <code>ssh -T git@github.com</code> 按回车键</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/git-ssh-generate/20201121204635.webp" alt="img"/><p>(｡･∀･)ﾉﾞ嗨 帅气的小嘉，您已经成功地通过了身份验证，但是 GitHub 不提供 shell 访问的呢</p><p>如果你看到这句话的时候，那就表示成功啦!!</p>]]></content>
    
    
    <summary type="html">如果你点进来，那我就当作你知道ssh和https的作用以及区别了，这里我就不讲了这第一步肯定是检查下自己之前有没有生成</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Git" scheme="https://blog.imzjw.cn/tags/Git/"/>
    
  </entry>
  
  <entry>
    <title>使用 jsDelivr 加速静态文件</title>
    <link href="https://blog.imzjw.cn/posts/speed-jsdelivr/"/>
    <id>https://blog.imzjw.cn/posts/speed-jsdelivr/</id>
    <published>2020-11-20T09:30:07.000Z</published>
    <updated>2020-12-15T10:19:07.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p><code>CDN </code> 的全称是 <code>Content Delivery Network</code>，即内容分发网络。CDN 是构建在网络之上的内容分发网络，依靠部署在各地的边缘服务器，通过中心平台的负载均衡、内容分发、调度等功能模块，使用户就近获取所需内容，降低网络拥塞，提高用户访问响应速度和命中率。CDN 的关键技术主要有内容存储和分发技术。—— <a href="https://baike.baidu.com/item/CDN/420951?fr=aladdin">百度百科</a></p><h2 id="如何操作"><a href="#如何操作" class="headerlink" title="如何操作?"></a>如何操作?</h2><ol><li>准备一个 Github 账号（自行百度 <a href="https://www.baidu.com/s?tn=02003390_hao_pg&ie=utf-8&wd=github%E6%80%8E%E4%B9%88%E6%B3%A8%E5%86%8C">GitHub 怎么注册</a> ）</li><li>懂得如何向 <a href="https://www.baidu.com/s?tn=02003390_hao_pg&ie=utf-8&wd=GitHub%20%E4%BB%93%E5%BA%93%20push%20%E6%96%87%E4%BB%B6">GitHub 仓库 push 文件</a></li></ol><h3 id="正式开始"><a href="#正式开始" class="headerlink" title="正式开始"></a>正式开始</h3><ol><li><p>准备仓库，仓库名称与描述随便写，但是仓库必须要求<code>公开</code>，不能是私有</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/speed-jsdelivr/image-20201120170845998.webp" alt="img"></p></li><li><p>准备一个文件</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/speed-jsdelivr/20201120171511.webp" alt="img"></p></li><li><p>上传文件</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git add .  # add 后面那个点表示所有文件</span><br><span class="line">git commit -m &#x27;添加文件内容描述&#x27;</span><br><span class="line">git push origin master   # 将本地仓库文件推送到GitHub新建的仓库</span><br></pre></td></tr></table></figure></li><li><p>通过 jsdelivr 引用资源</p><p>食用方法：<code>https://cdn.jsdelivr.net/gh/你的Github用户名/你的仓库名@发布的版本号/文件及路径</code></p><p>例如：<code>https://cdn.jsdelivr.net/gh/zjwo/test-file@master/jquery-1.11.1.min.js</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/speed-jsdelivr/20201120172032.webp" alt="img"></p><p><strong>注意</strong>：版本号不是必需的，是为了区分新旧资源，如果不使用版本号，将会直接引用最新资源</p><p><strong>直接引用：</strong></p><ul><li>格式为：<code>https://cdn.jsdelivr.net/gh/&lt;用户名&gt;/&lt;仓库名&gt;/&lt;文件及路径&gt;</code></li></ul><p><strong>分支及版本号：</strong></p><ul><li>分支与版本号加到仓库后，用 @ 符链接。格式为： <code>https://cdn.jsdelivr.net/gh/&lt;用户名&gt;/&lt;仓库名&gt;@[分支/版本号]/&lt;文件及路径&gt;</code></li></ul></li></ol><h2 id="关于缓存问题"><a href="#关于缓存问题" class="headerlink" title="关于缓存问题"></a>关于缓存问题</h2><div class="note warning flat"><p>如果你修改了文件，重新 push 上去，你会发现没有变化，导致无法在第一时间更新。</p></div><h3 id="解决办法"><a href="#解决办法" class="headerlink" title="解决办法"></a>解决办法</h3><ol><li><p>使用  <code>purge</code>  替换</p><p>在原先的 url 中，将  <code>https://cdn.jsdelivr.net/...</code>  替换为  <code>https://purge.jsdelivr.net/…</code>  刷新</p></li><li><p>使用 jsDelivr 缓存清除工具</p><p>使用 jsDelivr 缓存清除工具可实时自动的去更新调试 </p></li></ol><div class="note warning flat"><p>2020.12.15更新 - 缓存清除工具 参考：<a href="https://wr0926.ml/p/6e9b38bb/index.html?_sw-precache=fdfb3939b7522ff763c648bf69e41138#%E5%85%B3%E4%BA%8E-JsDelivr">JsDelivr刷新缓存工具</a></p></div><h2 id="其它问题"><a href="#其它问题" class="headerlink" title="其它问题"></a>其它问题</h2><ol><li><p>GitHub 公开仓库大小为 100 GB，所以不用担心不够用的问题了。并且你可以创建无数个仓库💗</p></li><li><p>但是单仓库容量超过 1 G后，会有人工审核仓库内容，若发现用来做图床，轻则删库，重则封号</p></li><li><p>建议在 1G 之前就应该换个仓库继续做图床！hhhhhhh~</p></li><li><p>Github 单文件上传为 100 M，但是 JSD 加速的单文件大小为 50 M。所以也就意味着单文件大小为 50 MB 。</p></li><li><p>图片视频静态文件基本都是可以の</p></li></ol><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>jsDelivr 和 GitHub 配合使用还是非常好用的，还请各位不要滥用💝</p>]]></content>
    
    
    <summary type="html">CDN 的全称是 Content Delivery Network，即内容分发网络。CDN 是构建在网络之上的内容分发网络，依靠部署在各地的边缘服务器，通过中心平台的负载均衡、内容分发、调度等功能模块</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="jsDelivr" scheme="https://blog.imzjw.cn/tags/jsDelivr/"/>
    
  </entry>
  
  <entry>
    <title>设计模式-工厂模式</title>
    <link href="https://blog.imzjw.cn/posts/designMode-factory/"/>
    <id>https://blog.imzjw.cn/posts/designMode-factory/</id>
    <published>2020-11-17T04:16:22.000Z</published>
    <updated>2020-12-09T03:22:11.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><p><code>工厂模式</code> 是一种创建型设计模式，其在父类中提供一个创建对象的方法，允许子类决定实例化对象的类型。</p><h2 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h2><p>假如我们开发项目中的日志模块，业务初期只有控制台日志，大部分代码都在控制台日志类。随着业务发展，希望可以增加文件日志功能。</p><p>如果代码之间已经存在耦合关系，此时向程序添加新类并不是一件简单的事情。目前大部分代码都与控制台日志类有关。添加文件日志类需要修改全部代码，更可怕的是以后万一要拓展其他日志类，很可能需要再次大幅修改代码。</p><p>如此反复反复，恭喜, 成功诞生一份不可维护的祖传代码。 😂</p><h2 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h2><p>工厂方法模式建议使用特殊的工厂方法代替直接调用 <code>new</code> 关键字创建对象。工厂方法返回的对象通常被称作 “产品”。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">Logger</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">log</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConsoleLogger</span> <span class="keyword">extends</span> <span class="title class_">Logger</span> &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">log</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;我是控制台日志器！&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">FileLogger</span> <span class="keyword">extends</span> <span class="title class_">Logger</span> &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">log</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;我是文件日志器！&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>紧接着我们再创建一个工厂类，这里声明为抽象类，并且设置一个抽象方法，强制子类实现抽象方法。你也可以不设置成抽象类，在基础工厂方法中返回默认类型。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">LoggerFactory</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">abstract</span> Logger <span class="title function_">createLogger</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConsoleLoggerFactory</span> <span class="keyword">extends</span> <span class="title class_">LoggerFactory</span> &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Logger <span class="title function_">createLogger</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ConsoleLogger</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">FileLoggerFactory</span> <span class="keyword">extends</span> <span class="title class_">LoggerFactory</span> &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Logger <span class="title function_">createLogger</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">FileLogger</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/designMode-factory/factory.webp" alt="img"></p><p>乍看之下，工厂模式看起来毫无意义，只是改变了程序中调用构造函数的位置而已。但是我们可以在子类里重写工厂方法，从而改变其创建产品的类型。</p><p>但有一点需要注意，仅当这些产品具有共同的父类或者接口时，工厂子类才能返回不同类型的产品。同时工厂基类的工厂方法还应将其返回类型声明为共有接口。</p><p>只要产品类实现一个共同的接口，就可以将它传递给客户代码，而无需提供任何额外的数据。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Application</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> LoggerFactory loggerFactory;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Application</span><span class="params">(LoggerFactory loggerFactory)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.loggerFactory = loggerFactory;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">Logger</span> <span class="variable">logger</span> <span class="operator">=</span> loggerFactory.createLogger();</span><br><span class="line">        logger.log();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>客户端代码仅通过抽象类型使用工厂和产品，如需要添加新的产品，仅需实现工厂抽象类和产品抽象类即可。无需修改原有的工厂或者产品类。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>这是重新学习工厂模式的笔记，其中可能有很多地方写的不对，写得不好，欢迎大家指正 👏</p>]]></content>
    
    
    <summary type="html">工厂模式 是一种创建型设计模式，其在父类中提供一个创建对象的方法，允许子类决定实例化对象的类型。场景：假如我们开发项目中的日志模块</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="设计模式" scheme="https://blog.imzjw.cn/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
    
  </entry>
  
  <entry>
    <title>设计模式-单例模式</title>
    <link href="https://blog.imzjw.cn/posts/designMode-singleton/"/>
    <id>https://blog.imzjw.cn/posts/designMode-singleton/</id>
    <published>2020-11-17T03:28:22.000Z</published>
    <updated>2020-12-11T08:10:54.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><p><code>单例模式</code> 是一种创建型设计模式 👷，能够保证一个类只有一个 <code>实例</code>，并提供一个访问该实例的全局节点。</p><h2 id="特点"><a href="#特点" class="headerlink" title="特点"></a>特点</h2><ul><li>就是保证一个类只有一个实例。最常见的原因是控制某些共享资源，例如数据库或文件的访问权限。它的运作方式是这样的，如果此时你创建了一个对象，过一会你决定再创建一个对象，但是此时你会获得刚才已经创建好的对象，而不会产生一个新对象。⚠️ 要注意的是，普通构造函数无法实现，构造函数的设计决定了它一定要产生一个新对象。</li><li>为该实例提供一个全局访问节点，单例模式允许在程序任何地方访问特定对象。但是它可以保护该实例不会被其他代码所覆盖。</li></ul><h2 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h2><p>将默认构造函数设置为私有，防止其他对象使用单例类的 <code>new</code> 关键字进行实例化。</p><p>新建一个静态构造方法作为构造函数。该函数会调用私有构造函数来创建对象，无论何时调用该方法，它总是会返回相同的对象😎</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Singleton</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> Singleton instance;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="title function_">Singleton</span><span class="params">()</span> &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title function_">getInstance</span><span class="params">()</span> &#123;</span><br><span class="line">        ...</span><br><span class="line">        ...</span><br><span class="line">        ...</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="懒汉模式"><a href="#懒汉模式" class="headerlink" title="懒汉模式"></a>懒汉模式</h3><div class="tabs" id="第一种"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="第一种-1">第一种</button><button type="button" class="tab " data-href="第一种-2">第二种</button><button type="button" class="tab " data-href="第一种-3">第三种</button><button type="button" class="tab " data-href="第一种-4">第四种</button></ul><div class="tab-contents"><div class="tab-item-content active" id="第一种-1"><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title function_">getInstance</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (Objects.isNull(instance)) &#123;</span><br><span class="line">        instance = <span class="keyword">new</span> <span class="title class_">Singleton</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> instance;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="note warning flat"><p>这种方式实现起来十分简单，但是如果多线程访问单例对象，无法保证线程安全</p></div></div><div class="tab-item-content" id="第一种-2"><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">synchronized</span> Singleton <span class="title function_">getInstance</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (Objects.isNull(instance)) &#123;</span><br><span class="line">        instance = <span class="keyword">new</span> <span class="title class_">Singleton</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> instance;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="note warning flat"><p>使用 <code>synchronized</code> 关键字控制多线程访问，同一时刻只有一个线程可以进入代码块，确保了线程安全。但是这种方式会降低程序运行效率。</p></div></div><div class="tab-item-content" id="第一种-3"><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title function_">getInstance</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (Objects.isNull(instance)) &#123;</span><br><span class="line">        <span class="keyword">synchronized</span> (Singleton.class) &#123;</span><br><span class="line">            <span class="keyword">if</span> (Objects.isNull(instance)) &#123;</span><br><span class="line">                instance = <span class="keyword">new</span> <span class="title class_">Singleton</span>();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> instance;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="note warning flat"><p>使用双重校验的方式，既确保了线程安全，也不会影响程序运行效率。但是会出现空指针的风险。</p></div></div><div class="tab-item-content" id="第一种-4"><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title function_">getInstance</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> StaticSingletonHolder.INSTANCE;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">StaticSingletonHolder</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Singleton</span> <span class="variable">INSTANCE</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Singleton</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="note success flat"><p>使用静态内部类的方式，确保不会重复创建对象，也不会影响程序效率。并且还是懒加载的方式，内存方面也处理的非常好。</p></div></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="饿汉模式"><a href="#饿汉模式" class="headerlink" title="饿汉模式"></a>饿汉模式</h3><div class="tabs" id="第一种"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="第一种-1">第一种</button><button type="button" class="tab " data-href="第一种-2">第二种</button></ul><div class="tab-contents"><div class="tab-item-content active" id="第一种-1"><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Singleton</span> <span class="variable">INSTANCE</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Singleton</span>();</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title function_">getInstance</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> INSTANCE;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="note primary flat"><p>使用 final 静态成员变量，当类第一次加载到内存中的时候就完成了初始化，保证了线程安全。</p></div></div><div class="tab-item-content" id="第一种-2"><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> SingletonUsingEnum <span class="title function_">getInstance</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> SingletonUsingEnum.INSTANCE;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">enum</span> <span class="title class_">SingletonUsingEnum</span> &#123;</span><br><span class="line">    INSTANCE;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="note success flat"><p>使用枚举的方式，可以保证不会重复创建对象，线程安全。还可以避免反射和序列化等带来的问题。是实现单例模式最好的方式。</p></div></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>这是重新学习单例模式的笔记，其中可能有很多地方写的不对，写得不好，欢迎大家指正 👏</p>]]></content>
    
    
    <summary type="html">单例模式是一种创建型设计模式 👷，能够保证一个类只有一个 实例，并提供一个访问该实例的全局节点。特点就是保证一个类只有一个实例。最常见的原因是控制某些共享资源</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="设计模式" scheme="https://blog.imzjw.cn/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
    
  </entry>
  
  <entry>
    <title>GitHub Actions 自动部署 Hexo</title>
    <link href="https://blog.imzjw.cn/posts/df27ccfb/"/>
    <id>https://blog.imzjw.cn/posts/df27ccfb/</id>
    <published>2020-11-15T02:23:11.000Z</published>
    <updated>2020-11-15T02:23:11.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>GitHub Actions 是 GitHub 于 2018 年推出的自动化流程工具，它的功能很强大。因为是 GitHub 自家的工具，所以我们无需再额外注册账号，而且 GitHub Actions 也集成在了 GitHub 界面上。</p><h2 id="创建仓库"><a href="#创建仓库" class="headerlink" title="创建仓库"></a>创建仓库</h2><p>在 GitHub 上创建<code>俩</code>仓库，一个是源码仓（<code>blog</code>），一个是静态仓（<code>xxx.github.io</code>）静态仓相信你已经有了</p><p>关于隐私问题，再创建源码仓的时候，请设为私有（<code>Private</code>）</p><h2 id="创建-Actions"><a href="#创建-Actions" class="headerlink" title="创建 Actions"></a>创建 Actions</h2><p>在你的博客根目录创建 <code>.github\workflows\main.yml</code></p><p>也可以右键 <code>Git Bash</code> 执行如下命令：</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> .github &amp;&amp; <span class="built_in">cd</span> .github &amp;&amp; <span class="built_in">mkdir</span> workflows &amp;&amp; <span class="built_in">cd</span> workflows &amp;&amp; <span class="built_in">touch</span> main.yml</span><br></pre></td></tr></table></figure><p>打开 <code>main.yml</code>，复制如下代码</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">name:</span> <span class="string">Auto</span> <span class="string">Dep</span> <span class="string">Hexo</span></span><br><span class="line"></span><br><span class="line"><span class="attr">on:</span> </span><br><span class="line">  <span class="attr">push:</span></span><br><span class="line">    <span class="attr">branches:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">master</span> <span class="comment"># 如果你的是 main 那就改 main</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">release:</span></span><br><span class="line">    <span class="attr">types:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">published</span></span><br><span class="line"></span><br><span class="line"><span class="attr">jobs:</span></span><br><span class="line">  <span class="attr">deploy:</span></span><br><span class="line">    <span class="attr">runs-on:</span> <span class="string">ubuntu-latest</span></span><br><span class="line">    <span class="attr">steps:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Check</span> <span class="string">分支</span></span><br><span class="line">      <span class="attr">uses:</span> <span class="string">actions/checkout@v2</span></span><br><span class="line">      <span class="attr">with:</span></span><br><span class="line">        <span class="attr">ref:</span> <span class="string">master</span> <span class="comment"># 如果你的是 main 那就改 main</span></span><br><span class="line"></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Install</span> <span class="string">Node</span></span><br><span class="line">      <span class="attr">uses:</span> <span class="string">actions/setup-node@v1</span></span><br><span class="line">      <span class="attr">with:</span></span><br><span class="line">        <span class="attr">node-version:</span> <span class="string">&quot;12.x&quot;</span></span><br><span class="line"></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Cache</span> <span class="string">依赖</span></span><br><span class="line">      <span class="attr">uses:</span> <span class="string">actions/cache@v2.1.1</span></span><br><span class="line">      <span class="attr">id:</span> <span class="string">cache-dependencies</span></span><br><span class="line">      <span class="attr">with:</span></span><br><span class="line">        <span class="attr">path:</span> <span class="string">node_modules</span></span><br><span class="line">        <span class="attr">key:</span> <span class="string">$&#123;&#123;runner.OS&#125;&#125;-$&#123;&#123;hashFiles(&#x27;**/package-lock.json&#x27;)&#125;&#125;</span>    </span><br><span class="line"></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Install</span> <span class="string">依赖</span></span><br><span class="line">      <span class="attr">if:</span> <span class="string">steps.cache.outputs.cache-hit</span> <span class="type">!=</span> <span class="string">&#x27;true&#x27;</span></span><br><span class="line">      <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">        export TZ=&#x27;Asia/Shanghai&#x27;</span></span><br><span class="line"><span class="string">        npm install hexo-cli -g</span></span><br><span class="line"><span class="string">        npm install --save</span></span><br><span class="line"><span class="string"></span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">生成</span> <span class="string">Static</span> <span class="string">File</span></span><br><span class="line">      <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">        hexo clean</span></span><br><span class="line"><span class="string">        hexo generate</span></span><br><span class="line"><span class="string">        gulp# 如果你没用到 gulp 压缩，请注释</span></span><br><span class="line"><span class="string"></span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Deploy</span></span><br><span class="line">      <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">        git config --global user.name &quot;github-actions&quot;</span></span><br><span class="line"><span class="string">        git config --global user.email &quot;github-actions@users.noreply.github.com&quot;</span></span><br><span class="line"><span class="string">        # 这里请改成你静态的仓库</span></span><br><span class="line"><span class="string">        git clone https://github.com/xxx/xxx.github.io.git .deploy_git</span></span><br><span class="line"><span class="string">        hexo deploy</span></span><br></pre></td></tr></table></figure><h2 id="生成-TOKEN"><a href="#生成-TOKEN" class="headerlink" title="生成 TOKEN"></a>生成 TOKEN</h2><p>前往<a href="https://github.com/settings/tokens/new">生成 TOKEN</a> ，名字随意，勾选 <code>repo</code>，然后复制 <code>TOKEN</code> 记在小本本上，因为只会显示一次，忘记也没事，可以重新生成</p><p>修改博客根目录的配置文件（<code>_config.yml</code>）格式如下图，<code>xxx</code> 代表你 <code>GitHub</code> 用户名，<code>xxx.github.io</code> 代表你博客的静态仓，最后那个是分支 ( 废话 )</p><p><code>https://TOKEN@github.com/xxx/xxx.github.io,master</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df27ccfb/9c29c2a8b98a7326b8fee663ec890cd7.webp" alt="img"></p><h2 id="推送"><a href="#推送" class="headerlink" title="推送"></a>推送</h2><p>是吧整个博客推送到刚刚创建的私有仓，然后是利用 Actions 自动化部署到你的静态仓</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git add .</span><br><span class="line">git commit -m <span class="string">&quot;update&quot;</span></span><br><span class="line">git push -u origin master <span class="comment"># 是 main 你就改 main</span></span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df27ccfb/62e77c2d38775018da1357a257ddbe54.webp" alt="img"></p><h2 id="已知问题"><a href="#已知问题" class="headerlink" title="已知问题"></a>已知问题</h2><p>主题目录下有 <code>.git</code> （隐藏文件）自动部署失败</p><p><strong>解决：</strong></p><p>直接 <kbd>SHIFT</kbd> ➕ <kbd>DEL</kbd> 掉，简单粗暴 😊</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/df27ccfb/427842b3cb2a9da9f55daa9c3d59ed8a.webp" alt="img"></p>]]></content>
    
    
    <summary type="html">GitHub Actions 是 GitHub 于 2018 年推出的自动化流程工具，它的功能很强大。因为是 GitHub 自家的工具，所以我们无需再额外注册账号，而且 GitHub Actions 也集成在了 GitHub 界面上</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="GitHub Actions" scheme="https://blog.imzjw.cn/tags/GitHub-Actions/"/>
    
  </entry>
  
  <entry>
    <title>为你的valine评论添加微信、QQ通知</title>
    <link href="https://blog.imzjw.cn/posts/valineAddInform/"/>
    <id>https://blog.imzjw.cn/posts/valineAddInform/</id>
    <published>2020-11-12T13:03:57.000Z</published>
    <updated>2020-12-12T02:22:26.000Z</updated>
    
    <content type="html"><![CDATA[<div class="note blue icon-padding flat"><i class="note-icon fas fa-bullhorn"></i><p>在添加微信、QQ 通知之前，请务必将 <code>Deploy from</code> 修改成</p><p><del><a href="https://github.com/GarveyZhong/Valine-Admin-Server.git">https://github.com/GarveyZhong/Valine-Admin-Server.git</a></del> 我己经删库了</p><p>用 <a href="https://www.lete114.top/">乐特</a> 的这个，效果是一样的</p><p><a href="https://github.com/lete114/Valine-Admin-Server.git">https://github.com/lete114/Valine-Admin-Server.git</a></p></div><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/valineAddInform/ay86jg1EkWrzqKA.webp" height="450" alt="img"><h2 id="申请-Qmsg-酱"><a href="#申请-Qmsg-酱" class="headerlink" title="申请 Qmsg 酱"></a>申请 Qmsg 酱</h2><p>打开<a class="btn-beautify pink" href="https://qmsg.zendee.cn/"   title="官网"><i class="far fa-hand-point-right"></i><span>官网</span></a></p><p>点击<code>登陆</code> (我选择的是 QQ 登陆), 然后随便选一个给你通知的小姐姐</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/valineAddInform/VarbGWL3vX4sM9m.webp" height="450" alt="img"><p>接着点击右上角文档</p><p>把 <code>send</code> 后面的 <code>key</code> 复制到 <code>Leancloud</code> 的 <code>QMSG_KEY</code> 环境变量后保存即可</p><h3 id="Qmsg酱不推送的原因"><a href="#Qmsg酱不推送的原因" class="headerlink" title="Qmsg酱不推送的原因"></a>Qmsg酱不推送的原因</h3><ol><li><p>没有加 <code>Qmsg 酱</code> 小姐姐们的QQ号</p></li><li><p>没有添加<code>被通知者</code>的QQ号</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/valineAddInform/20201112212410.webp" alt="img"></p></li></ol><h2 id="申请-Server-酱"><a href="#申请-Server-酱" class="headerlink" title="申请 Server 酱"></a>申请 Server 酱</h2><p>Server 酱也就是微信通知啦 <a class="btn-beautify blue" href="https://sc.ftqq.com/3.version"   title="官网"><i class="far fa-hand-point-right"></i><span>官网</span></a></p><p>步骤和 Qmsg 类似</p><p>登录 ==&gt; 发送消息  ==&gt; 就可以得到 <code>SCKEY</code> 代码了</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/valineAddInform/20201112214536.webp" alt="img"></p><p>把 <code>SCKEY</code> 代码 <kbd>CTRL</kbd> + <kbd>C</kbd>  <kbd>CTRL</kbd> + <kbd>V</kbd> 到 <code>Leancloud</code> 的 <code>SCKEY</code> 环境变量 并 重启</p><p>接着点击右上角的微信推送进行绑定微信即可微信通知啦!!!</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/valineAddInform/20201112220552.webp" alt="img"></p><p>最后附上我的坏境变量</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/valineAddInform/20201112215306.webp" alt="img"></p><p>上图中的邮件主题模板</p><table><thead><tr><th>主题</th><th>说明</th></tr></thead><tbody><tr><td>default</td><td>默认主题</td></tr><tr><td>rainbow</td><td>原版的 rainbow</td></tr><tr><td>custom1</td><td>基于🎉梨花町の肾兄さん🎉的模板</td></tr><tr><td>custom2</td><td>对 custom1 的改进版</td></tr></tbody></table>]]></content>
    
    
    <summary type="html">在添加微信、QQ 通知之前，请务必将 Deploy from 修改成 Valine-Admin-Server.git，我己经删库了，用乐特的这个，效果是一样的，申请 Qmsg 酱，点击登陆 (我选择的是 QQ 登陆), 然后随便选一个给你通知的小姐姐</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="Valine" scheme="https://blog.imzjw.cn/tags/Valine/"/>
    
  </entry>
  
  <entry>
    <title>Vercel托管你的静态博客</title>
    <link href="https://blog.imzjw.cn/posts/hexo-vercel-config/"/>
    <id>https://blog.imzjw.cn/posts/hexo-vercel-config/</id>
    <published>2020-11-11T11:35:37.000Z</published>
    <updated>2021-05-12T03:22:44.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p><del>本站已托管至  <a href="https://vercel.com/">Vercel</a> ,  所以就想写一篇博客记录一下。</del> 现已部署至 <a href="https://www.upyun.com/">upyun</a> + <a href="https://github.com/">GitHub</a></p><h2 id="注册登录"><a href="#注册登录" class="headerlink" title="注册登录"></a>注册登录</h2><p>点击 Vercel <a class="btn-beautify pink" href="https://vercel.com/"   title="官网"><i class="far fa-hand-point-right"></i><span>官网</span></a>  并使用 GitHub 登录。</p><div class="note blue icon-padding flat"><i class="note-icon fas fa-bullhorn"></i><p>注意 <code>GitHub</code> 账户绑定的主邮箱📪，估计国内邮箱，比如 QQ 邮箱，163 邮箱会出现无法使用 GitHub 账号登陆 Vercel 的情况，推荐将 GitHub 主邮箱改为谷歌邮箱也就是 <a href="https://mail.google.com/">Gmail</a></p></div><div class="note danger flat"><p>Vercel 页面发生了小变化，前往 <a href="https://blog.imzjw.cn/posts/33155a20/">利用 GitHub + Vercel 来做视频床</a> 查看，操作都是大同小异，主要是懒的编辑文章了</p></div><h2 id="导入仓库"><a href="#导入仓库" class="headerlink" title="导入仓库"></a>导入仓库</h2><ul><li><p>点击 <code>Overview</code>  选择 <code>Import Project</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexo-vercel-config/20201111210115.webp" alt="img"></p></li><li><p>然后选择导入Git 仓库</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexo-vercel-config/20201111210329.webp" alt="img"></p></li><li><p>复制自己的 GitHub 博客地址链接（这里指的是静态仓库，也就是你的 <code>xxx.github.io</code> 那个仓库，不是源码仓）</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexo-vercel-config/20201111210753.webp" alt="img"></p></li><li><p>等待导入成功</p></li></ul><h2 id="自定义域名"><a href="#自定义域名" class="headerlink" title="自定义域名"></a>自定义域名</h2><p>进入 <code>dashboard</code>，点击项目卡片 –&gt; View Domains</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexo-vercel-config/20201111211345.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexo-vercel-config/20201111211410.webp" alt="View Domains"></p><div class="note primary flat"><p>如果你想使用<code>Vercel</code> 提供的二级域名，直接添加 <code>xxx.now.sh</code> 或 <code>xxx.vercel.app</code>  看你想要哪个，如果没有人用过的话，会自动验证成功。</p></div><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexo-vercel-config/20201111211623.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexo-vercel-config/20201111211708.webp" alt="img">如果你想绑定自己的域名，就在输入框中输入你想要绑定的网址，点击右侧 Add 即可。下方会提示 <code>Invalid Config</code>，然后在域名购买方控制台进行域名解析。解析完成后即可通过自己的域名访问自己的博客。</p><ul><li>如果是根域名，请在你的 DNS 解析处添加 A 记录，指向 <code>76.76.21.21</code></li><li>如果是子域名，请在你的 DNS 解析处添加 CNAME 记录，指向 <code>cname.vercel-dns.com</code></li></ul><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/hexo-vercel-config/20201111211917.webp" alt="img"></p><p>至此 Vercel 的部署过程就结束了</p><p>如果你在部署过程中有什么问题，可以在下方留言。</p>]]></content>
    
    
    <summary type="html">本站已托管至 Vercel，所以就想写一篇博客记录一下。现已托管至 upyun + Github，点击 Verce 官网,并使用GitHub登录，注意 GitHub 账户绑定的主邮箱📪</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="Vercel" scheme="https://blog.imzjw.cn/tags/Vercel/"/>
    
  </entry>
  
  <entry>
    <title>使用springboot发送Email</title>
    <link href="https://blog.imzjw.cn/posts/boot-email/"/>
    <id>https://blog.imzjw.cn/posts/boot-email/</id>
    <published>2020-11-02T14:17:10.000Z</published>
    <updated>2020-11-02T14:17:10.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在实际项目中，经常需要用到邮件通知功能。比如，用户通过邮件注册，通过邮件找回密码等；又比如通过邮件发送系统情况，通过邮件发送报表信息等等，实际应用场景很多。(但一般都是使用手机验证码🙂)</p><p>这篇文章，就教大家通过 <code>springboot</code> 快速的实现一个发送邮件的功能。</p><h2 id="开启-smtp"><a href="#开启-smtp" class="headerlink" title="开启 smtp"></a>开启 smtp</h2><p>这里以 QQ 邮箱为例。登录 QQ 邮箱之后，点击设置，点击账户。如下图</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/boot-email/20201102222311.webp" alt="img"></p><p>点击开启 <code>IMAP/SMTP</code> 服务。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/boot-email/20201102222409.webp" alt="img"></p><p>开启之后，记下 QQ 邮箱提示的<code>授权码</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/boot-email/1.webp" alt="img"></p><div class="note info flat"><p>这个授权码，就是发送邮件时需要的密码。以上步骤完成之后，就可以开始开发了。</p></div><h2 id="引入依赖"><a href="#引入依赖" class="headerlink" title="引入依赖"></a>引入依赖</h2><p>创建 springboot 项目就不需要讲了叭</p><p>在 springboot 项目中，引入如下依赖</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-mail<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="配置文件"><a href="#配置文件" class="headerlink" title="配置文件"></a>配置文件</h2><p>在 springboot 项目中引入依赖之后，即可在其配置文件中配置邮箱的参数</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">mail:</span></span><br><span class="line">    <span class="attr">host:</span> <span class="string">smtp.qq.com</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">garveyzhong@foxmail.com</span></span><br><span class="line">    <span class="attr">password:</span> <span class="string">xxxxxxxxx</span></span><br><span class="line">    <span class="attr">protocol:</span> <span class="string">smtp</span></span><br><span class="line">    <span class="attr">default-encoding:</span> <span class="string">UTF-8</span></span><br></pre></td></tr></table></figure><p>因为是 QQ 邮箱，所以 <code>host</code> 填写 <code>smtp.qq.com</code> 。如果是其它邮箱的话，请 <a href="https://blog.csdn.net/ning521513/article/details/79217203">点击</a> 查看对应的 <code>smtp</code> 地址</p><p><code>username</code> 为邮箱账号，<code>password</code> 为上面步骤中提到的授权码，并不是你的 QQ 密码</p><h2 id="注入-JavaMailSender-实例"><a href="#注入-JavaMailSender-实例" class="headerlink" title="注入 JavaMailSender 实例"></a>注入 JavaMailSender 实例</h2><p>邮箱参数配置完之后，即可直接注入 JavaMailSender 实例</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> JavaMailSender javaMailSender;</span><br></pre></td></tr></table></figure><h2 id="发送普通邮件"><a href="#发送普通邮件" class="headerlink" title="发送普通邮件"></a>发送普通邮件</h2><p>普通邮件，没有样式。实现起来最容易</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 邮件发送者</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">FROM</span> <span class="operator">=</span> <span class="string">&quot;garveyzhong@foxmail.com&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 邮件接收者</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">TO</span> <span class="operator">=</span> <span class="string">&quot;782718644@qq.com&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">sendMail</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">SimpleMailMessage</span> <span class="variable">message</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SimpleMailMessage</span>();</span><br><span class="line">    message.setFrom(FROM);</span><br><span class="line">    message.setTo(TO);</span><br><span class="line">    message.setSubject(<span class="string">&quot;这是标题&quot;</span>);</span><br><span class="line">    message.setText(<span class="string">&quot;这是内容&quot;</span>);</span><br><span class="line">    javaMailSender.send(message);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li><code>From</code> 需要和配置文件中的  <code>username </code> 一致，否则会报错。</li><li><code>To</code> 为邮件接收者；</li><li><code>Subject</code> 为邮件的标题；</li><li><code>Text</code> 为邮件的内容。</li></ul><p>运行方法，即可收到邮件</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/boot-email/20201102223646.webp" alt="img"></p><h2 id="发送HTML邮件"><a href="#发送HTML邮件" class="headerlink" title="发送HTML邮件"></a>发送HTML邮件</h2><p>很多时候，我们需要邮件带有美观的样式。这时候，可以使用HTML的样式。我们需要使用 <code>javaMailSender</code> 的 <code>createMimeMessage</code> 方法，构建一个 <code>MimeMessage</code>，然后使用 <code>MimeMessage</code> 实例创建出 <code>MimeMessageHelper</code>。如下</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">sendHtmlMail</span><span class="params">()</span> <span class="keyword">throws</span> MessagingException &#123;</span><br><span class="line">    <span class="type">MimeMessage</span> <span class="variable">mimeMessage</span> <span class="operator">=</span> javaMailSender.createMimeMessage();</span><br><span class="line">    <span class="type">MimeMessageHelper</span> <span class="variable">messageHelper</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MimeMessageHelper</span>(mimeMessage);</span><br><span class="line">    messageHelper.setSubject(<span class="string">&quot;标题&quot;</span>);</span><br><span class="line">    messageHelper.setFrom(FROM);</span><br><span class="line">    messageHelper.setTo(TO);</span><br><span class="line">    messageHelper.setText(<span class="string">&quot;&lt;h1&gt;标题&lt;/h1&gt;&lt;br/&gt;&lt;p&gt;这是内容&lt;/p&gt;&quot;</span>, <span class="literal">true</span>);</span><br><span class="line">    javaMailSender.send(messageHelper.getMimeMessage());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里需要注意的是，<code>setText</code> 的时候需要传一个<code>布尔值</code> 进去，表明 需要使用HTML样式。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/boot-email/20201102224301.webp" alt="img"></p><p>可以看到，h1 的样式已经出来了。</p>]]></content>
    
    
    <summary type="html">在实际项目中，经常需要用到邮件通知功能。比如，用户通过邮件注册，通过邮件找回密码等；又比如通过邮件发送系统情况，通过邮件发送报表信息等等，实际应用场景很多</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Spring Boot" scheme="https://blog.imzjw.cn/tags/Spring-Boot/"/>
    
  </entry>
  
  <entry>
    <title>Linux查看端口进程</title>
    <link href="https://blog.imzjw.cn/posts/2000000/"/>
    <id>https://blog.imzjw.cn/posts/2000000/</id>
    <published>2020-10-29T12:54:10.000Z</published>
    <updated>2020-10-29T12:54:10.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在我们日常 Linux 服务器维护时候都会去看一下端口和端口上具体运行的进程，有时想明确知道 Linux 服务器端口被什么进程占用。下面详细的讲解下 Linux 查看端口进程的两种方法。</p><h2 id="Linux查看端口进程"><a href="#Linux查看端口进程" class="headerlink" title="Linux查看端口进程"></a>Linux查看端口进程</h2><h3 id="方法一"><a href="#方法一" class="headerlink" title="方法一"></a>方法一</h3><p>使用命令：<code>netstat –apn</code>，查看所有的进程和端口使用情况，找到端口对应的 <code>PID</code>。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[root@xiaojia ~]# netstat -apn</span><br></pre></td></tr></table></figure><p>使用命令：<code>ps -aux | grep pid</code> 查看对应的进程</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[root@xiaojia ~]# ps -aux | grep 6379</span><br></pre></td></tr></table></figure><h3 id="方法二"><a href="#方法二" class="headerlink" title="方法二"></a>方法二</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[root@xiaojia ~]# netstat -apn | grep 8080</span><br></pre></td></tr></table></figure><p>属实不知道写什么文章了，今晚就水一篇文章叭 😅</p>]]></content>
    
    
    <summary type="html">在我们日常 Linux 服务器维护时候都会去看一下端口和端口上具体运行的进程，有时想明确知道 Linux 服务器端口被什么进程占用。下面详细的讲解下 Linux 查看端口进程的两种方法。</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Linux" scheme="https://blog.imzjw.cn/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>Hexo+Butterfly进行百度、Google收录</title>
    <link href="https://blog.imzjw.cn/posts/afc2/"/>
    <id>https://blog.imzjw.cn/posts/afc2/</id>
    <published>2020-10-26T13:52:10.000Z</published>
    <updated>2020-12-09T13:52:10.000Z</updated>
    
    <content type="html"><![CDATA[<div class="note danger flat"><p>本博主已弃用此插件, 也不是说不能用，建议参考 <a href="https://blog.lete114.top/article/hexo-seo-autopush.html">Hexo 每天自动提交网站url到搜索引擎</a></p></div><div class="note danger flat"><p>本文教程仅针对于 <a href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a> 主题，绝对保姆🙉🙉，其他主题我不清楚，参考乐特的这篇文章：<a href="https://blog.lete114.top/article/b6c07012.html#%E5%89%8D%E8%A8%80">Hexo + yilia 进行 SEO 优化、百度收录、Google (谷歌)收录</a></p></div><h2 id="配置-robots-txt"><a href="#配置-robots-txt" class="headerlink" title="配置 robots.txt"></a>配置 robots.txt</h2><h3 id="什么是-robots？"><a href="#什么是-robots？" class="headerlink" title="什么是 robots？"></a>什么是 robots？</h3><p>这里就不仔细介绍了，建议 <a class="btn-beautify blue" href="https://baike.baidu.com/item/robots/5243374?fr=aladdin"   title="百科"><i class="far fa-hand-point-right"></i><span>百科</span></a></p><p>robots 是站点与 spider 沟通的重要渠道，站点通过 robots 文件声明本网站中不想被搜索引擎收录的部分或者指定搜索引擎只收录特定的部分。</p><div class="note info flat"><p>可以用我写好的，修改自己的相应配置即可，如有更高的需求可以前往 <a class="btn-beautify pink" href="https://ziyuan.baidu.com/college/courseinfo?id=267&page=12#h2_article_title30"   title="robots.txt 文件的格式"><i class="far fa-hand-point-right"></i><span>robots.txt 文件的格式</span></a></p></div><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 允许所有用户代理的浏览器爬虫进行访问（爬取数据）</span></span><br><span class="line"><span class="attr">User-agent:</span> <span class="string">*</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 不允许访问的内容</span></span><br><span class="line"><span class="attr">Disallow:</span> <span class="string">/img/</span></span><br><span class="line"><span class="attr">Disallow:</span> <span class="string">/css/</span></span><br><span class="line"><span class="attr">Disallow:</span> <span class="string">/js/</span></span><br><span class="line"><span class="attr">Disallow:</span> <span class="string">/photos/</span></span><br><span class="line"><span class="attr">Disallow:</span> <span class="string">/*.css</span></span><br><span class="line"><span class="attr">Disallow:</span> <span class="string">/*.js</span></span><br><span class="line"></span><br><span class="line"><span class="attr">Sitemap:</span> <span class="string">https://blog.imzjw.cn/sitemap.xml</span></span><br><span class="line"><span class="attr">Sitemap:</span> <span class="string">https://blog.imzjw.cn/baidusitemap.xml</span></span><br></pre></td></tr></table></figure><p>可能就有人问，这配置放在哪？别急</p><p>首先，新建个<code>robots.txt</code>文件，然后把上面的配置 <code>cv</code> 并修改成你自己相对应的配置，接着把这个 <code>robots.txt</code> 文件放在博客根目录下的 <code>source</code> 文件夹下面</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/1.webp" alt="img"/><div class="note warning flat"><p>最后最后，最最关键的，在博客根目录下的配置文件( _config.yml )，配置 <code>skip_render</code>，其目的就是跳过渲染</p></div><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/2.webp" alt="img"/><p>之后可以去 <a class="btn-beautify blue" href="https://ziyuan.baidu.com/robots"   title="百度站长平台"><i class="far fa-hand-point-right"></i><span>百度站长平台</span></a> 检测一下有没有生效</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/20201101220724.webp" alt="img" width="80%" height="450"/><h2 id="百度收录"><a href="#百度收录" class="headerlink" title="百度收录"></a>百度收录</h2><ol><li><p>百度搜索框内输入 <code>site:你的域名</code>如：<code>site:imzjw.cn</code> 后点击提交网址或者直接前往 <a class="btn-beautify purple" href="https://zhanzhang.baidu.com/"   title="百度搜索资源平台"><i class="far fa-hand-point-right"></i><span>百度搜索资源平台</span></a></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/20201101221230.webp" alt="img"/></li><li><p>这一步需要的截图过多，会影响博客的加载速度，我就适当的截图，<code>仔细看文字，别漏了每一行字</code></p><p>注册百度账号，登录，点击用户中心，站点管理，选择添加网站，输入你自己的博客域名（建议https）</p><p>最后点击<code>管理站点</code>进行<code>验证站点</code>，站点领域随便瞎填几个，看你站点主要干啥的</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/20201026223705.webp" alt="img"/></li><li><p>紧接着验证网站，三种验证方式，看自己喜欢，本文是HTML标签验证，也是博主喜欢的验证方式</p><p>把 <code>content</code> 的属性值 <code>cv</code> 到主题的配置文件的 <code>baidu_site_verification</code>，这配置仅针对于 <code>Butterfly</code> 主题，其他主题我不清楚</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/20201026224216.webp" alt="img"/><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/20201026224608.webp" alt="img"/></li></ol><div class="note info flat"><p>最后 hexo cl &amp;&amp; hexo g &amp;&amp; hexo d 部署上去，完成验证</p></div><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/20201026230950.webp" alt="img"/><h2 id="推送方式"><a href="#推送方式" class="headerlink" title="推送方式"></a>推送方式</h2><ol><li>手动提交：一次性提交链接给百度，可以使用此种方式。</li><li>自动提交（虽然这种方式各有千秋，但是百度推荐全用上，全面一点！）<ul><li>主动推送（实时）：最为快速的提交方式，推荐您将站点当天新产出链接立即通过此方式推送给百度，以保证新链接可以及时被百度收录。</li><li>自动推送：最为便捷的提交方式，请将自动推送的 JS 代码部署在站点的每一个页面源代码中，部署代码的页面在每次被浏览时，链接会被自动推送给百度。可以与主动推送配合使用。</li><li>sitemap：您可以定期将网站链接放到 sitemap 中，然后将 sitemap 提交给百度。百度会周期性的抓取检查您提交的 sitemap，对其中的链接进行处理，但收录速度慢于主动推送。</li></ul></li></ol><h3 id="设置推送"><a href="#设置推送" class="headerlink" title="设置推送"></a>设置推送</h3><p>点击前往 <a class="btn-beautify green" href="https://ziyuan.baidu.com/"   title="站长平台"><i class="far fa-hand-point-right"></i><span>站长平台</span></a></p><p><code>前提</code>：注册百度，添加站点、验证站点。这些完成之后才可接着下一步推送</p><p>验证成功就能在百度找到你的网站了，百度搜索框输入：如 <code>site:imzjw.cn</code>，但百度没有那么快，可能需要一两个星期甚至一个月 (谷歌的话当天就可以收入，或者明天)。</p><h3 id="主动推送"><a href="#主动推送" class="headerlink" title="主动推送"></a>主动推送</h3><p>百度站长工具，然后在<code>（标题栏）搜索服务 --&gt; 普通收录 --&gt; 资源提交 --&gt; 普通收录</code>。</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/biAQrpWPITG1Yce.webp" alt="img"/><p>添加插件 <a class="btn-beautify " href="https://github.com/huiwang/hexo-baidu-url-submit"   title="hexo-baidu-url-submit"><i class="far fa-hand-point-right"></i><span>hexo-baidu-url-submit</span></a></p><p>首先，在 Hexo 根目录下右键选择 Git Bash Here, 输入：<code>npm install hexo-baidu-url-submit --save</code> 安装插件</p><h3 id="配置-百度主动推送"><a href="#配置-百度主动推送" class="headerlink" title="配置  百度主动推送"></a>配置  百度主动推送</h3><p>同样在根目录下，把以下内容配置到<code>_config.yml</code> 文件中，注意是博客的根目录噢</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 百度主动推送</span></span><br><span class="line"><span class="attr">baidu_url_submit:</span></span><br><span class="line">  <span class="attr">count:</span> <span class="number">100</span> <span class="comment"># 提交最新的一个链接</span></span><br><span class="line">  <span class="attr">host:</span> <span class="string">imzjw.cn</span> <span class="comment"># 在百度站长平台中注册的域名</span></span><br><span class="line">  <span class="attr">token:</span> <span class="string">YourToken</span> <span class="comment"># 请注意这是你百度站长平台主动推送的的秘钥, 所以请不要把博客源代码发布在公众仓库里!</span></span><br><span class="line">  <span class="attr">path:</span> <span class="string">baidu_urls.txt</span> <span class="comment"># 文本文档的地址, 新链接会保存在此文本文档里</span></span><br></pre></td></tr></table></figure><p>最后，加入新的 deploy (可以参考一下我的<code>_config.yml</code> 文件)</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">deploy:</span> <span class="comment"># 定义部署</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">type:</span> <span class="string">git</span></span><br><span class="line">    <span class="attr">repo:</span></span><br><span class="line">      <span class="attr">github:</span> <span class="string">https://github.com/XXX/XXX.git,master</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">type:</span> <span class="string">baidu_url_submitter</span></span><br><span class="line">  </span><br><span class="line"><span class="comment"># 百度主动推送</span></span><br><span class="line"><span class="attr">baidu_url_submit:</span></span><br><span class="line">  <span class="attr">count:</span> <span class="number">100</span> <span class="comment"># 提交最新的100个链接</span></span><br><span class="line">  <span class="attr">host:</span> <span class="string">imzjw.cn</span> <span class="comment"># 在百度站长平台中注册的域名</span></span><br><span class="line">  <span class="attr">token:</span> <span class="string">YourToken</span> <span class="comment"># 请注意这是你百度站长平台主动推送的的秘钥, 所以请不要把博客源代码发布在公众仓库里!</span></span><br><span class="line">  <span class="attr">path:</span> <span class="string">baidu_urls.txt</span> <span class="comment"># 文本文档的地址, 新链接会保存在此文本文档里</span></span><br></pre></td></tr></table></figure><h3 id="如何进行推送"><a href="#如何进行推送" class="headerlink" title="如何进行推送"></a>如何进行推送</h3><p>执行 <code>hexo d</code> 的时候，新的链接就会被推送了。如下图</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/20201027111549.webp" alt="img" height="450"/><p>重新生成后，我们可以发现在 <code>public</code> 目录下生成有 <code>baidu_urls.txt</code> 里面的就是推送的链接。</p><h3 id="自动推送"><a href="#自动推送" class="headerlink" title="自动推送"></a>自动推送</h3><p>在配置 <code>Butterfly主题下的_config.yml</code> 中开启功能</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Baidu Push (百度推送)</span></span><br><span class="line"><span class="attr">baidu_push:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><p><code>ps</code>：但是 <a href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a> 作者 <a href="https://jerryc.me/">杰瑞</a> 它说这一项没用，开启也没用，因为要绑定<code>主体</code></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/UbwsGOHvyK6rn8d.webp" alt="img" height="450"/><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/20201027113811.webp" alt="img" height="450"/><p>既然杰瑞说到 <code>sitemap</code> 提交，那我们就来 <code>sitemap</code> 提交叭</p><h3 id="sitemap-提交"><a href="#sitemap-提交" class="headerlink" title="sitemap 提交"></a>sitemap 提交</h3><p>我们使用<a class="btn-beautify green" href="https://github.com/coneycode/hexo-generator-baidu-sitemap"   title="hexo generator-baidu-sitemap"><i class="far fa-hand-point-right"></i><span>hexo generator-baidu-sitemap</span></a>这个插件</p><p>安装 <code>hexo generator-baidu-sitemap</code> 插件</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="keyword">if</span> your hexo version is 2.x.x, you should install as follow:</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">如果你的hexo版本是2.x.x，你应该安装如下</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">npm install hexo-generator-baidu-sitemap@0.0.8 --save</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="keyword">if</span> version is 3.x.x, you should install as follow:</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">如果版本是3.x.x，你应该安装如下</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">npm install hexo-generator-baidu-sitemap --save</span></span><br></pre></td></tr></table></figure><p>不知道自己hexo啥版本的，可以在博客的根目录下有个<code>package.json</code>进行查看，我的是 <code>5.2.0</code></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/20201101221553.webp" alt="img" /><p>然后在博客的根目录下的<code>_config.yml</code> 里面<code>手动</code>加入配置</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">baidusitemap:</span></span><br><span class="line">  <span class="attr">path:</span> <span class="string">baidusitemap.xml</span></span><br></pre></td></tr></table></figure><p><code>hexo g</code> 后，会在 <code>public</code> 目录下生成站点文件 <code>baidusitemap.xml</code>。</p><p>之后去百度站长平台提交一下 sitemap 的路径就好，如：https://你的博客地址/baidusitemap.xml</p><h3 id="效果"><a href="#效果" class="headerlink" title="效果"></a>效果</h3><p>在站长平台可以看到链接提交数量，如：</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/20201027115518.webp" alt="img" /><h2 id="Google-收录"><a href="#Google-收录" class="headerlink" title="Google 收录"></a>Google 收录</h2><div class="note blue icon-padding flat"><i class="note-icon fas fa-bullhorn"></i><p>Google收录其实没什么好讲的, 你不找他, 他自然会找你, 也duck不必往下看了，当然你想看我也不拦着你</p></div><h3 id="添加网站、验证"><a href="#添加网站、验证" class="headerlink" title="添加网站、验证"></a>添加网站、验证</h3><p>登录 Google 账号，打开<a class="btn-beautify pink" href="https://search.google.com/search-console"   title="谷歌搜索控制台"><i class="far fa-hand-point-right"></i><span>谷歌搜索控制台</span></a>  添加你的网站，需要验证网站，它那里会提供几种验证方式，验证方式和baidu一样</p><p>验证成功不是当天就是明天就能在 Google 找到你的网站了，谷歌搜索输入如 <code>site:imzjw.cn</code></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/20201109130113.webp" alt="img" /><h3 id="谷歌-sitemap-提交"><a href="#谷歌-sitemap-提交" class="headerlink" title="谷歌 sitemap 提交"></a>谷歌 sitemap 提交</h3><p>提交 sitemap，上面使用的是百度的 sitemap 也可以，如果 Google 识别不了，可以使用通用 sitemap 生成器 </p><p>安装<a class="btn-beautify pink" href="https://github.com/hexojs/hexo-generator-sitemap"   title="hexo-generator-sitemap"><i class="far fa-hand-point-right"></i><span>hexo-generator-sitemap</span></a>插件</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-generator-sitemap --save</span><br></pre></td></tr></table></figure><p>配置 博客根目录下 的<code>_config.yml</code>, 手动输入以下配置</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">sitemap:</span> </span><br><span class="line">  <span class="attr">path:</span> <span class="string">sitemap.xml</span></span><br></pre></td></tr></table></figure><p>执行 <code>hexo g</code> 重新生成，会在 <code>public</code> 目录下生成 <code>sitemap.xml</code> 文件，发布后，就可以在 Google 控制台提交这个 sitemap 了。</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/afc2/20201027115958.webp" alt="img" />]]></content>
    
    
    <summary type="html">本文教程仅针对于 Butterfly 主题，绝对保姆，其他主题我不清楚，参考乐特的这篇文章：Hexo + yilia 进行 SEO 优化、百度收录、Google (谷歌)收录</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>MySQL测试循环插入千万级数据</title>
    <link href="https://blog.imzjw.cn/posts/7671/"/>
    <id>https://blog.imzjw.cn/posts/7671/</id>
    <published>2020-10-09T13:07:01.000Z</published>
    <updated>2020-10-09T13:07:01.000Z</updated>
    
    <content type="html"><![CDATA[<h3 id="创建测试表"><a href="#创建测试表" class="headerlink" title="创建测试表"></a>创建测试表</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> `xiaojia` (</span><br><span class="line">`id` <span class="type">INT</span> (<span class="number">11</span>) <span class="keyword">NOT</span> <span class="keyword">NULL</span> AUTO_INCREMENT,</span><br><span class="line">`uuid` <span class="type">VARCHAR</span> (<span class="number">50</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>,</span><br><span class="line"><span class="keyword">PRIMARY</span> KEY (`id`)</span><br><span class="line">) ENGINE <span class="operator">=</span> INNODB AUTO_INCREMENT <span class="operator">=</span> <span class="number">5999001</span> <span class="keyword">DEFAULT</span> CHARSET <span class="operator">=</span> utf8;</span><br></pre></td></tr></table></figure><h3 id="创建一个循环插入的存储过程"><a href="#创建一个循环插入的存储过程" class="headerlink" title="创建一个循环插入的存储过程"></a>创建一个循环插入的存储过程</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">PROCEDURE</span> `xiaojia`( )</span><br><span class="line">    <span class="keyword">BEGIN</span> </span><br><span class="line">    <span class="keyword">DECLARE</span> i <span class="type">INT</span> <span class="keyword">DEFAULT</span> <span class="number">0</span>;</span><br><span class="line">    WHILE i <span class="operator">&lt;</span> <span class="number">10000</span> DO</span><br><span class="line">        <span class="keyword">INSERT</span> <span class="keyword">INTO</span> xiaojia(uuid) <span class="keyword">VALUES</span>(UUID());</span><br><span class="line">        <span class="keyword">SET</span> i <span class="operator">=</span> i <span class="operator">+</span> <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">END</span> WHILE;</span><br><span class="line"><span class="keyword">END</span>;</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7671/sql.webp" alt="img"></p><div class='checkbox times red checked'><input type="checkbox" checked="checked"/>            <p><strong>调用刚刚创建的存储过程</strong> <code>call test_xiaojia();</code> <strong>测试，发现一万条数据耗时 <code>52</code> 秒，如果是千万级数据，这个速度将无法忍受。😥</strong></p>            </div><h3 id="优化存储过程"><a href="#优化存储过程" class="headerlink" title="优化存储过程"></a>优化存储过程</h3><div class="note info flat"><p>优化的方法也是在网上找到的，用的是拼接批量插入的 <code>sql</code> 语句，可以发现速度确实提升很多😝</p></div><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">PROCEDURE</span> `xiaojiaPlus`(<span class="keyword">IN</span> sum <span class="type">INT</span>)</span><br><span class="line">    <span class="keyword">BEGIN</span></span><br><span class="line">    <span class="keyword">DECLARE</span> count <span class="type">INT</span> <span class="keyword">DEFAULT</span> <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">DECLARE</span> i <span class="type">INT</span> <span class="keyword">DEFAULT</span> <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">SET</span> <span class="variable">@exesql</span> <span class="operator">=</span> concat(&quot;INSERT INTO xiaojia(uuid) VALUES&quot;);</span><br><span class="line">    <span class="keyword">SET</span> <span class="variable">@exedata</span> <span class="operator">=</span> &quot;&quot;;</span><br><span class="line">    <span class="keyword">SET</span> count <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">SET</span> i <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">    WHILE count <span class="operator">&lt;</span> sum DO</span><br><span class="line">        <span class="keyword">SET</span> <span class="variable">@exedata</span> <span class="operator">=</span> concat(<span class="variable">@exedata</span>, &quot;,(UUID())&quot;);</span><br><span class="line">        <span class="keyword">SET</span> count <span class="operator">=</span> count <span class="operator">+</span> <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">SET</span> i <span class="operator">=</span> i <span class="operator">+</span> <span class="number">1</span>;</span><br><span class="line">        IF i <span class="operator">%</span> <span class="number">1000</span> <span class="operator">=</span> <span class="number">0</span> <span class="keyword">THEN</span></span><br><span class="line">            <span class="keyword">SET</span> <span class="variable">@exedata</span> <span class="operator">=</span> <span class="built_in">SUBSTRING</span>( <span class="variable">@exedata</span>, <span class="number">2</span> );</span><br><span class="line">            <span class="keyword">SET</span> <span class="variable">@exesql</span> <span class="operator">=</span> concat(&quot;INSERT INTO xiaojia(uuid) VALUES&quot;, <span class="variable">@exedata</span>);</span><br><span class="line">            <span class="keyword">PREPARE</span> stmt <span class="keyword">FROM</span> <span class="variable">@exesql</span>;</span><br><span class="line">            <span class="keyword">EXECUTE</span> stmt;</span><br><span class="line">            <span class="keyword">DEALLOCATE</span> <span class="keyword">PREPARE</span> stmt;</span><br><span class="line">            <span class="keyword">SET</span> <span class="variable">@exedata</span> <span class="operator">=</span> &quot;&quot;;</span><br><span class="line">        <span class="keyword">END</span> IF;</span><br><span class="line">    <span class="keyword">END</span> WHILE;</span><br><span class="line">    IF length( <span class="variable">@exedata</span> ) <span class="operator">&gt;</span> <span class="number">0</span> <span class="keyword">THEN</span></span><br><span class="line">        <span class="keyword">SET</span> <span class="variable">@exedata</span> <span class="operator">=</span> <span class="built_in">SUBSTRING</span>( <span class="variable">@exedata</span>, <span class="number">2</span>);</span><br><span class="line">        <span class="keyword">SET</span> <span class="variable">@exesql</span> <span class="operator">=</span> concat(&quot;INSERT INTO xiaojia(uuid) VALUES&quot;, <span class="variable">@exedata</span>);</span><br><span class="line">        <span class="keyword">PREPARE</span> stmt <span class="keyword">FROM</span> <span class="variable">@exesql</span>;</span><br><span class="line">        <span class="keyword">EXECUTE</span> stmt;</span><br><span class="line">        <span class="keyword">DEALLOCATE</span> <span class="keyword">PREPARE</span> stmt;</span><br><span class="line">    <span class="keyword">END</span> IF;</span><br><span class="line"><span class="keyword">END</span>;</span><br></pre></td></tr></table></figure><div class='checkbox blue checked'><input type="checkbox" checked="checked"/>            <p><strong>调用</strong> <code>CALL xiaojiaPlus(10000);</code> <strong>耗时零点几秒，这速度可以接受，这才是真男人</strong></p>            </div><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7671/sql2.webp" alt="img"></p><ul><li>本文优化就到这了😁</li></ul>]]></content>
    
    
    <summary type="html">创建测试表,创建一个循环插入的存储过程,调用刚刚创建的存储过程测试，发现一万条数据耗时 52 秒，如果是千万级数据，这个速度将无法忍受，优化存储过程</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="MySQL" scheme="https://blog.imzjw.cn/tags/MySQL/"/>
    
  </entry>
  
  <entry>
    <title>GitHub 个人主页美化</title>
    <link href="https://blog.imzjw.cn/posts/1a4c5f9f/"/>
    <id>https://blog.imzjw.cn/posts/1a4c5f9f/</id>
    <published>2020-10-05T07:23:37.000Z</published>
    <updated>2020-10-05T07:23:37.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>今天在逛 <a href="https://github.com/">GitHub</a> 时，发现一个有意思的地方，在看到某些大佬的GitHub主页时，发现多了一个类似自我介绍的东西，因此我也来折腾了一下</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1a4c5f9f/57f2c3497cc97f6e556f936ab7dec86b.webp" alt="img"><h2 id="实现方式"><a href="#实现方式" class="headerlink" title="实现方式"></a>实现方式</h2><p>其实这个实现起来也是比较简单的，新建一个仓库，和自己 GiHub 用户名相同即可</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/1a4c5f9f/ef3b888d6c5f404d655cc0ad0bfc1669.webp" alt="img"><p>当仓库名和用户一样时，就会跳出来一个蓝猫，并说着</p><p>您发现了一个秘密！ zjwo/zjwo 是一个特殊存储库，可用于将 <code>README.md</code> 添加到您的 GitHub 个人资料中。确保它是公开的，并使用自述文件对其进行初始化以开始使用。</p><p>通过上述我们知道需要注意的几个点就是</p><ol><li>仓库必须是 Public （公开的）</li><li>添加一个 <code>README</code> 文件</li></ol><p>接下来就是在  <code>README.md</code>  文件中编写你想添加的东西即可，比如上面截图中的个人项目统计，常用语言等卡片</p><p>可以参考此 <a href="https://github.com/anuraghazra/github-readme-stats">仓库</a></p></br><psw>看不懂？</psw>  没关系，有中文文档<div class="btns rounded grid5">            <a class="button" href='https://github.com/anuraghazra/github-readme-stats/blob/master/docs/readme_cn.md' title='中文文档'><i class='fas fa-book-open'></i>中文文档</a>          </div><p>如果实在不想自己写的话，可以打开此 <a href="https://github.com/kautukkundan/Awesome-Profile-README-templates">仓库</a>，里面收录了很多优秀的模板，然后自己 <kbd>C</kbd> <kbd>V</kbd>过来，涂涂改改就是自己的了</p><p>我的 GitHub 个人主页代码如下：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="section"># 𝗛𝗲𝗹𝗹𝗼！<span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://user-images.githubusercontent.com/5679180/79618120-0daffb80-80be-11ea-819e-d2b0fa904d07.gif&quot;</span> <span class="attr">width</span>=<span class="string">&quot;27px&quot;</span>&gt;</span></span> </span></span><br><span class="line"></span><br><span class="line">𝗜&#x27;𝗺 [<span class="string">garvey</span>](<span class="link">https://github.com/zjwo</span>)！𝗜&#x27;𝗺 𝗮 𝘀𝗼𝗳𝘁𝘄𝗮𝗿𝗲 𝗲𝗻𝗴𝗶𝗻𝗲𝗲𝗿 👨‍💻 𝘄𝗵𝗼 𝗶𝘀 𝗽𝗮𝘀𝘀𝗶𝗼𝗻𝗮𝘁𝗲 𝗮𝗯𝗼𝘂𝘁 𝗺𝘂𝘀𝗶𝗰 𝗮𝗻𝗱 𝗼𝗽𝗲𝗻 𝘀𝗼𝘂𝗿𝗰𝗲.</span><br><span class="line"></span><br><span class="line">[<span class="string">![Twitter Badge</span>](<span class="link">https://img.shields.io/badge/-Twitter-1da1f2?style=flat-square&amp;labelColor=1da1f2&amp;logo=twitter&amp;logoColor=white&amp;link=https://twitter.com/Yaronzz</span>)](<span class="link">https://twitter.com/imzjwo</span>)</span><br><span class="line">[<span class="string">![Email Badge</span>](<span class="link">https://img.shields.io/badge/-Email-c14438?style=flat-square&amp;logo=Gmail&amp;logoColor=white&amp;link=mailto:yaronhuang@foxmail.com</span>)](<span class="link">mailto:admin@imzjw.cn</span>)</span><br><span class="line">[<span class="string">![Github Badge</span>](<span class="link">https://img.shields.io/badge/-Github-232323?style=flat-square&amp;logo=Github&amp;logoColor=white&amp;link=https://github.com/zjwo</span>)](<span class="link">https://github.com/zjwo</span>)</span><br><span class="line">![<span class="string">visitors</span>](<span class="link">https://visitor-badge.laobi.icu/badge?page_id=zjwo</span>)</span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">align</span>=<span class="string">&quot;right&quot;</span> <span class="attr">src</span>=<span class="string">&quot;https://github-readme-stats.vercel.app/api?username=zjwo&amp;show_icons=true&amp;hide_border=true&quot;</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="section">## 🧐 About</span></span><br><span class="line"></span><br><span class="line"><span class="bullet">-</span> 👨‍💻 My blog: https://blog.imzjw.cn</span><br><span class="line"><span class="bullet">-</span> 📫 How to reach me: lsp@imlsp.tk</span><br><span class="line"><span class="bullet">-</span> 🌱 Languages and Tools: </span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">code</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">width</span>=<span class="string">&quot;10%&quot;</span> <span class="attr">src</span>=<span class="string">&quot;https://www.vectorlogo.zone/logos/java/java-ar21.svg&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">code</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">code</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;https://www.linux.org/&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">height</span>=<span class="string">&quot;50&quot;</span> <span class="attr">src</span>=<span class="string">&quot;https://www.vectorlogo.zone/logos/linux/linux-ar21.svg&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">code</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">code</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;https://www.docker.com/&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">height</span>=<span class="string">&quot;50&quot;</span> <span class="attr">src</span>=<span class="string">&quot;https://www.vectorlogo.zone/logos/docker/docker-official.svg&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">code</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">br</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">code</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">width</span>=<span class="string">&quot;10%&quot;</span> <span class="attr">src</span>=<span class="string">&quot;https://www.vectorlogo.zone/logos/mysql/mysql-ar21.svg&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">code</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">code</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">width</span>=<span class="string">&quot;10%&quot;</span> <span class="attr">src</span>=<span class="string">&quot;https://raw.githubusercontent.com/github/explore/80688e429a7d4ef2fca1e82350fe8e3517d3494d/topics/git/git.png&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">code</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">br</span> /&gt;</span></span></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">今天在逛 GitHub 时，发现一个有意思的地方，在看到某些大佬的GitHub主页时，发现多了一个类似自我介绍的东西，因此我也来折腾了一下</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="GitHub" scheme="https://blog.imzjw.cn/tags/GitHub/"/>
    
  </entry>
  
  <entry>
    <title>Docker安装部署Oracle 11g</title>
    <link href="https://blog.imzjw.cn/posts/e7ff/"/>
    <id>https://blog.imzjw.cn/posts/e7ff/</id>
    <published>2020-07-25T03:31:38.000Z</published>
    <updated>2020-07-25T03:31:38.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="拉取镜像"><a href="#拉取镜像" class="headerlink" title="拉取镜像"></a>拉取镜像</h2><p>首先执行如下命令将镜像下载到本地（这个其实就是一个已经安装好 <code>Oracle</code> 数据库的镜像，我们运行后稍作配置就可以直接使用了）</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g</span><br></pre></td></tr></table></figure><h2 id="启动容器"><a href="#启动容器" class="headerlink" title="启动容器"></a>启动容器</h2><p>执行如下命令实例化 <code>Oracle</code> 服务</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -d -p 1521:1521 --name oracle11g registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g</span><br></pre></td></tr></table></figure><p>执行 <code>docker ps</code> 命令确认容器启动成功。</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e7ff/docker1.webp" alt="img"><h2 id="进行配置"><a href="#进行配置" class="headerlink" title="进行配置"></a>进行配置</h2><ul><li><p>首先执行如下命令进入 oracle 的命令环境中：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker exec -it oracle11g bash</span><br></pre></td></tr></table></figure></li><li><p>接着执行如下命令切换到  oracle 数据库的  root 用户下（密码为：<code>helowin</code>）</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">su root</span><br></pre></td></tr></table></figure></li><li><p>编辑  <code>profile</code> 文件：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vi /etc/profile</span><br></pre></td></tr></table></figure></li><li><p>在末尾处添加如下  ORACLE 环境变量参数后保存退出</p><div class="note danger flat"><p>注意：作者原先制作这个镜像时，设置的数据库 <code>SID</code> 为 <code>helowin</code>，所以这里的 <code>SID</code> 不做修改（emmm…因为要改 <code>SID</code> 的地方挺多的）</p></div><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">export ORACLE_HOME=/home/oracle/app/oracle/product/11.2.0/dbhome_2</span><br><span class="line">export ORACLE_SID=helowin</span><br><span class="line">export PATH=$ORACLE_HOME/bin:$PATH</span><br></pre></td></tr></table></figure></li><li><p>接着执行如下命令创建软连接</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ln -s $ORACLE_HOME /bin/sqlplus /usr/bin</span><br></pre></td></tr></table></figure></li><li><p>然后执行如下命令切换到 <code>oracle</code> 用户</p><div class="note danger flat"><p>注：一定要写中间的那一横条（-）必须要，否则软连接无效。</p></div><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">su - oracle</span><br></pre></td></tr></table></figure></li><li><p>接着依次执行如下命令登录 <code>sqlplus</code>：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sqlplus /nolog </span><br><span class="line"></span><br><span class="line">conn /as sysdba</span><br></pre></td></tr></table></figure><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e7ff/docker20200725115225.webp" alt="img"></li><li><p>执行如下命令将 system 和 sys 两个账户的密码设为 garvey</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">alter</span> <span class="keyword">user</span> <span class="keyword">system</span> identified <span class="keyword">by</span> garvey;</span><br><span class="line"><span class="keyword">alter</span> <span class="keyword">user</span> sys identified <span class="keyword">by</span> garvey;</span><br><span class="line"><span class="keyword">ALTER</span> PROFILE <span class="keyword">DEFAULT</span> LIMIT PASSWORD_LIFE_TIME UNLIMITED;</span><br></pre></td></tr></table></figure></li><li><p>我们还可以执行如下命令解锁 scott 用户，同时将其密码设置为 tiger</p><div class="note success flat"><p>SCOTT 是 ORACLE 内部的一个示例用户，下面有 emp、dept 等实例表，这些表和表间的关系演示了关系型数据库的一些基本原理。</p></div><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">alter</span> <span class="keyword">user</span> scott account unlock;</span><br><span class="line"><span class="keyword">alter</span> <span class="keyword">user</span> scott identified <span class="keyword">by</span> tiger;</span><br><span class="line"><span class="keyword">commit</span>;</span><br></pre></td></tr></table></figure></li><li><p>配置完毕后，连续执行多个 exit 即可退出容器，返回到宿主机。</p></li></ul><h2 id="连接测试"><a href="#连接测试" class="headerlink" title="连接测试"></a>连接测试</h2><p>我们使用 <code>Jetbrains</code> 出品的一款数据库连接工具 <a href="https://www.jetbrains.com/datagrip/">DataGrip</a> 来连接这个 Oracle 数据库（其中  SID 为  helowin），可以发现连接成功</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/e7ff/docker20200725152030.webp" alt="img">]]></content>
    
    
    <summary type="html">首先执行如下命令将镜像下载到本地（这个其实就是一个已经安装好 Oracle 数据库的镜像，我们运行后稍作配置就可以直接使用了，启动容器-执行如下命令实例化 Oracle 服务</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Docker" scheme="https://blog.imzjw.cn/tags/Docker/"/>
    
    <category term="Oracle" scheme="https://blog.imzjw.cn/tags/Oracle/"/>
    
  </entry>
  
  <entry>
    <title>MyBatis连接Oracle增删改查</title>
    <link href="https://blog.imzjw.cn/posts/d865/"/>
    <id>https://blog.imzjw.cn/posts/d865/</id>
    <published>2020-07-24T03:50:04.000Z</published>
    <updated>2020-07-24T03:50:04.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在 <code>Maven</code> 项目里是不能直接使用 <code>&lt;dependency&gt;</code> 导入的，需要手动添加到 Maven 本地仓库，我们在下载安装 Oracle 数据库的时候是自带了 ojdbc 的 jar 包的，我的 11g 版本 jar 在 <code>E:\oracle\jimulu\product\11.2.0\dbhome_1\jdbc\lib</code></p><p>利用 Maven 命令将 jar 包添加到本地仓库：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=12.1.0.1.0 -Dpackaging=jar -Dfile=E:\oracle\jimulu\product\11.2.0\dbhome_1\jdbc\lib\ojdbc6.jar</span><br></pre></td></tr></table></figure><p>解释一下上面命令：</p><ul><li>-DgroupId、-DartifactId、-Dversion 就是 <code>dependency</code> 的 groupId、artifactId、version 标签，不过 version 是当前所下载数据库的版本号</li><li>-Dfile 就是我们 ojdbc 的目录，就是将该 jar 包加入 Maven 本地仓库</li></ul><p>然后直接在 Maven 项目的 pom.xml 内配置依赖即可，标签内容要与所执行 maven 命令一致。</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--oracle 驱动包--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.oracle<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>ojdbc6<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>12.1.0.1.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="正式开始"><a href="#正式开始" class="headerlink" title="正式开始"></a>正式开始</h2><p>好，进入正题，首先在 Oracle 中创建 User 表</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">create</span> <span class="keyword">table</span> T_USERS </span><br><span class="line">( </span><br><span class="line">  ID      NUMBER <span class="keyword">not</span> <span class="keyword">null</span>, </span><br><span class="line">  NAME    VARCHAR2(<span class="number">30</span>), </span><br><span class="line">  SEX     VARCHAR2(<span class="number">3</span>), </span><br><span class="line">  BIRS    <span class="type">DATE</span>, </span><br><span class="line">  MESSAGE <span class="type">CLOB</span> </span><br><span class="line">); </span><br><span class="line"><span class="keyword">create</span> sequence SEQ_T_USERS_ID </span><br><span class="line">minvalue <span class="number">1</span> </span><br><span class="line">maxvalue <span class="number">99999999</span> </span><br><span class="line"><span class="keyword">start</span> <span class="keyword">with</span> <span class="number">1</span> </span><br><span class="line">increment <span class="keyword">by</span> <span class="number">1</span> </span><br><span class="line">cache <span class="number">20</span>;</span><br></pre></td></tr></table></figure><p>创建 User 实体类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">User</span> &#123;</span><br><span class="line"><span class="keyword">private</span> Integer id;</span><br><span class="line"><span class="keyword">private</span> String name;</span><br><span class="line"><span class="keyword">private</span> String sex;</span><br><span class="line"><span class="keyword">private</span> Date birs;</span><br><span class="line"><span class="keyword">private</span> String message;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>创建 UsersMapper 接口</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">UserMapper</span> &#123;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 添加用户</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> user</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">add</span><span class="params">(User user)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 修改用户</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> user</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">update</span><span class="params">(User user)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 根据id进行删除</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> id</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">delete</span><span class="params">(<span class="meta">@Param(&quot;id&quot;)</span> Integer id)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 根据id查询</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> id</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">User <span class="title function_">queryById</span><span class="params">(<span class="meta">@Param(&quot;id&quot;)</span> Integer id)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 列表总数</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> user</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">queryByCount</span><span class="params">(User user)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 查询列表</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> user</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">List&lt;User&gt; <span class="title function_">queryByList</span><span class="params">(User user)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>创建配置文件（ <code>mybatis-config.xml</code> ）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span> ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">configuration</span></span></span><br><span class="line"><span class="meta">        <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Config 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-config.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">typeAliases</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--给实体类起一个别名 user --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">type</span>=<span class="string">&quot;com.zjw.oracle.entity.User&quot;</span> <span class="attr">alias</span>=<span class="string">&quot;User&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">typeAliases</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--数据源配置  这块用 Oracle数据库 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">environments</span> <span class="attr">default</span>=<span class="string">&quot;development&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">environment</span> <span class="attr">id</span>=<span class="string">&quot;development&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">transactionManager</span> <span class="attr">type</span>=<span class="string">&quot;jdbc&quot;</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">dataSource</span> <span class="attr">type</span>=<span class="string">&quot;POOLED&quot;</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driver&quot;</span> <span class="attr">value</span>=<span class="string">&quot;oracle.jdbc.OracleDriver&quot;</span>/&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;url&quot;</span> <span class="attr">value</span>=<span class="string">&quot;jdbc:oracle:thin:@localhost:1521:orcl&quot;</span>/&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span> <span class="attr">value</span>=<span class="string">&quot;scott&quot;</span>/&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;tiger&quot;</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">dataSource</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">environment</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">environments</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mappers</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--UsersMapper.xml装载进来  同等于把“dao”的实现装载进来 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">mapper</span> <span class="attr">resource</span>=<span class="string">&quot;UserMapper.xml&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">mappers</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br></pre></td></tr></table></figure><p>UserMapper.xml</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">mapper</span></span></span><br><span class="line"><span class="meta">        <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--这块等于mapper接口的实现  namespace必须和接口的类路径一样--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;com.zjw.oracle.mapper.UserMapper&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- Result Map--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">type</span>=<span class="string">&quot;com.zjw.oracle.entity.User&quot;</span> <span class="attr">id</span>=<span class="string">&quot;BaseResultMap&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">&quot;id&quot;</span> <span class="attr">column</span>=<span class="string">&quot;id&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;name&quot;</span> <span class="attr">column</span>=<span class="string">&quot;name&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;sex&quot;</span> <span class="attr">column</span>=<span class="string">&quot;sex&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;birs&quot;</span> <span class="attr">column</span>=<span class="string">&quot;birs&quot;</span> <span class="attr">jdbcType</span>=<span class="string">&quot;TIMESTAMP&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;message&quot;</span> <span class="attr">column</span>=<span class="string">&quot;message&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 表名--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">sql</span> <span class="attr">id</span>=<span class="string">&quot;Tabel_Name&quot;</span>&gt;</span></span><br><span class="line">        t_users</span><br><span class="line">    <span class="tag">&lt;/<span class="name">sql</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 表中所有列 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">sql</span> <span class="attr">id</span>=<span class="string">&quot;Base_Column_List&quot;</span>&gt;</span></span><br><span class="line">        id, name, sex, birs, message</span><br><span class="line">    <span class="tag">&lt;/<span class="name">sql</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 查询条件 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">sql</span> <span class="attr">id</span>=<span class="string">&quot;Example_Where_Clause&quot;</span>&gt;</span></span><br><span class="line">        where 1 = 1</span><br><span class="line">        <span class="tag">&lt;<span class="name">trim</span> <span class="attr">suffixOverrides</span>=<span class="string">&quot;,&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;id != null&quot;</span>&gt;</span></span><br><span class="line">                and id = #&#123;id&#125;</span><br><span class="line">            <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;name != null and name != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">                and name like concat(concat(&#x27;%&#x27;, &#x27;$&#123;name&#125;&#x27;), &#x27;%&#x27;)</span><br><span class="line">            <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;sex != null and sex != &#x27;&#x27;&quot;</span>&gt;</span></span><br><span class="line">                and sex like concat(concat(&#x27;%&#x27;, &#x27;$&#123;sex&#125;&#x27;), &#x27;%&#x27;)</span><br><span class="line">            <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;birs != null&quot;</span>&gt;</span></span><br><span class="line">                and birs = #&#123;birs&#125;</span><br><span class="line">            <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;message != null&quot;</span>&gt;</span></span><br><span class="line">                and message = #&#123;message&#125;</span><br><span class="line">            <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">trim</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">sql</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 1.新增记录 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">insert</span> <span class="attr">id</span>=<span class="string">&quot;add&quot;</span> <span class="attr">parameterType</span>=<span class="string">&quot;User&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">selectKey</span> <span class="attr">resultType</span>=<span class="string">&quot;int&quot;</span> <span class="attr">order</span>=<span class="string">&quot;BEFORE&quot;</span> <span class="attr">keyProperty</span>=<span class="string">&quot;id&quot;</span>&gt;</span></span><br><span class="line">            select seq_t_users_id.nextval as id from dual</span><br><span class="line">        <span class="tag">&lt;/<span class="name">selectKey</span>&gt;</span></span><br><span class="line">        insert into t_users(id, name, sex, birs, message) values(#&#123;id&#125;, #&#123;name&#125;, #&#123;sex&#125;, #&#123;birs&#125;, #&#123;message&#125;)</span><br><span class="line">    <span class="tag">&lt;/<span class="name">insert</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 2.根据id修改记录--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">update</span> <span class="attr">id</span>=<span class="string">&quot;update&quot;</span> <span class="attr">parameterType</span>=<span class="string">&quot;User&quot;</span>&gt;</span></span><br><span class="line">        update t_users set name = #&#123;name&#125;, sex = #&#123;sex&#125;, birs = #&#123;birs&#125;, message = #&#123;message&#125; where id = #&#123;id&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">update</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 3.根据id进行删除 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">delete</span> <span class="attr">id</span>=<span class="string">&quot;delete&quot;</span>&gt;</span></span><br><span class="line">        delete from t_users where id = #&#123;id&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">delete</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 4.根据id查询 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;queryById&quot;</span> <span class="attr">resultMap</span>=<span class="string">&quot;BaseResultMap&quot;</span>&gt;</span></span><br><span class="line">        select</span><br><span class="line">        <span class="tag">&lt;<span class="name">include</span> <span class="attr">refid</span>=<span class="string">&quot;Base_Column_List&quot;</span>/&gt;</span></span><br><span class="line">        from t_users where id = #&#123;id&#125;</span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 5.列表总数 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;queryByCount&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;java.lang.Integer&quot;</span> <span class="attr">parameterType</span>=<span class="string">&quot;User&quot;</span>&gt;</span></span><br><span class="line">        select count(1) from t_users</span><br><span class="line">        <span class="tag">&lt;<span class="name">include</span> <span class="attr">refid</span>=<span class="string">&quot;Example_Where_Clause&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 6.查询列表 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;queryByList&quot;</span> <span class="attr">resultMap</span>=<span class="string">&quot;BaseResultMap&quot;</span> <span class="attr">parameterType</span>=<span class="string">&quot;User&quot;</span>&gt;</span></span><br><span class="line">        select</span><br><span class="line">        <span class="tag">&lt;<span class="name">include</span> <span class="attr">refid</span>=<span class="string">&quot;Base_Column_List&quot;</span>/&gt;</span></span><br><span class="line">        from t_users</span><br><span class="line">        <span class="tag">&lt;<span class="name">include</span> <span class="attr">refid</span>=<span class="string">&quot;Example_Where_Clause&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure><p>在 main 方法中测试</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OracleTest</span> &#123;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">RESOURCE</span> <span class="operator">=</span> <span class="string">&quot;mybatis-config.xml&quot;</span>;</span><br><span class="line"></span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">      <span class="comment">//                                               ---&gt;      true: 表示自动提交</span></span><br><span class="line">      <span class="type">SqlSession</span> <span class="variable">sqlSession</span> <span class="operator">=</span> getSqlSessionFactory().openSession(<span class="literal">true</span>);</span><br><span class="line">      <span class="type">UserMapper</span> <span class="variable">userMapper</span> <span class="operator">=</span> sqlSession.getMapper(UserMapper.class);</span><br><span class="line"></span><br><span class="line">      <span class="comment">// 添加用户</span></span><br><span class="line">      <span class="comment">// userMapper.add(new User(null, &quot;xiaojia&quot;, &quot;男&quot;, getData(&quot;2000-01-01&quot;), &quot;你好，我是小嘉，个人博客:https://blog.imzjw.cn&quot;));</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">// 根据id删除指定的用户</span></span><br><span class="line">      <span class="comment">// userMapper.delete(1);</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">// 修改用户</span></span><br><span class="line">      <span class="comment">// userMapper.update(new User(1, &quot;xiaojia&quot;, &quot;男&quot;, getData(&quot;2000-02-02&quot;), &quot;你好，我是小嘉，个人博客:https://blog.imzjw.cn&quot;));</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">// 查询用户个数</span></span><br><span class="line">      <span class="comment">// System.out.println(userMapper.queryByCount(new User()));</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">// 查询所有用户</span></span><br><span class="line">      <span class="keyword">for</span> (User user : userMapper.queryByList(<span class="keyword">new</span> <span class="title class_">User</span>())) &#123;</span><br><span class="line">         System.out.println(user);</span><br><span class="line">      &#125;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="comment">/**</span></span><br><span class="line"><span class="comment">    * 获取SqlSessionFactory</span></span><br><span class="line"><span class="comment">    *</span></span><br><span class="line"><span class="comment">    * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">   <span class="keyword">private</span> <span class="keyword">static</span> SqlSessionFactory <span class="title function_">getSqlSessionFactory</span><span class="params">()</span> &#123;</span><br><span class="line">      <span class="type">SqlSessionFactory</span> <span class="variable">sessionFactory</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">      <span class="keyword">try</span> &#123;</span><br><span class="line">         sessionFactory = <span class="keyword">new</span> <span class="title class_">SqlSessionFactoryBuilder</span>().build(Resources.getResourceAsReader(RESOURCE));</span><br><span class="line">      &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">         e.printStackTrace();</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> sessionFactory;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="comment">/**</span></span><br><span class="line"><span class="comment">    * 格式化日期</span></span><br><span class="line"><span class="comment">    *</span></span><br><span class="line"><span class="comment">    * <span class="doctag">@param</span> bir</span></span><br><span class="line"><span class="comment">    * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">   <span class="keyword">private</span> <span class="keyword">static</span> Date <span class="title function_">getData</span><span class="params">(String bir)</span> &#123;</span><br><span class="line">      <span class="type">DateFormat</span> <span class="variable">df</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SimpleDateFormat</span>(<span class="string">&quot;yyyy-MM-dd&quot;</span>);</span><br><span class="line">      <span class="type">Date</span> <span class="variable">date</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">      <span class="keyword">try</span> &#123;</span><br><span class="line">         date = df.parse(bir);</span><br><span class="line">      &#125; <span class="keyword">catch</span> (ParseException e) &#123;</span><br><span class="line">         e.printStackTrace();</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> date;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d865/1.webp" alt="images"></p>]]></content>
    
    
    <summary type="html">在 Maven 项目里是不能直接使用 &lt;dependency&gt; 导入的，需要手动添加到 Maven 本地仓库，我们在下载安装 Oracle 数据库的时候是自带了ojdbc 的 jar 包的，我的 11g 版本 jar 在</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="MyBatis" scheme="https://blog.imzjw.cn/tags/MyBatis/"/>
    
  </entry>
  
  <entry>
    <title>IDEA常用快捷键</title>
    <link href="https://blog.imzjw.cn/posts/63724/"/>
    <id>https://blog.imzjw.cn/posts/63724/</id>
    <published>2020-06-22T15:37:35.000Z</published>
    <updated>2020-06-22T15:37:35.000Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>说 IDEA 对新手来说难，可能其中一个原因就是快捷键组合多而且复杂但是它也很全，基本所有功能都可以通过快捷键来完成，可以这么说，如果你掌握了所有 IDEA 的快捷键使用，那么你完全可以丢掉鼠标，而且不影响开发效率。</p></div><h2 id="Ctrl-快捷键"><a href="#Ctrl-快捷键" class="headerlink" title="Ctrl 快捷键"></a>Ctrl 快捷键</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">Ctrl + F    在当前文件进行文本查找 （必备）</span><br><span class="line">Ctrl + R    在当前文件进行文本替换 （必备）</span><br><span class="line">Ctrl + Z    撤销 （必备）</span><br><span class="line">Ctrl + Y    删除光标所在行 或 删除选中的行 （必备）</span><br><span class="line">Ctrl + X    剪切光标所在行 或 剪切选择内容</span><br><span class="line">Ctrl + C    复制光标所在行 或 复制选择内容</span><br><span class="line">Ctrl + D    复制光标所在行 或 复制选择内容，并把复制内容插入光标位置下面 （必备）</span><br><span class="line">Ctrl + W    递进式选择代码块。可选中光标所在的单词或段落，连续按会在原有选中的基础上再扩展选中范围（必备）</span><br><span class="line">Ctrl + E    显示最近打开的文件记录列表 （必备）</span><br><span class="line">Ctrl + N    根据输入的 名/类名 查找类文件 （必备）</span><br><span class="line">Ctrl + G    在当前文件跳转到指定行处</span><br><span class="line">Ctrl + J    插入自定义动态代码模板 （必备）</span><br><span class="line">Ctrl + P    方法参数提示显示 （必备）</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Ctrl + Q    光标所在的变量 / 类名 / 方法名等上面（也可以在提示补充的时候按），显示文档内容</span><br><span class="line">Ctrl + U    前往当前光标所在的方法的父类的方法 / 接口定义 （必备）</span><br><span class="line">Ctrl + B    进入光标所在的方法/变量的接口或是定义处，等效于 Ctrl + 左键单击 （必备）</span><br><span class="line">Ctrl + K    版本控制提交项目，需要此项目有加入到版本控制才可用</span><br><span class="line">Ctrl + T    版本控制更新项目，需要此项目有加入到版本控制才可用</span><br><span class="line">Ctrl + H    显示当前类的层次结构</span><br><span class="line">Ctrl + O    选择可重写的方法</span><br><span class="line">Ctrl + I    选择可继承的方法</span><br><span class="line">Ctrl + +    展开代码</span><br><span class="line">Ctrl + -    折叠代码</span><br><span class="line">Ctrl + /    释光标所在行代码，会根据当前不同文件类型使用不同的注释符号 （必备）</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Ctrl + [    移动光标到当前所在代码的花括号开始位置</span><br><span class="line">Ctrl + ]    移动光标到当前所在代码的花括号结束位置</span><br><span class="line">Ctrl + F1   在光标所在的错误代码处显示错误信息 （必备）</span><br><span class="line">Ctrl + F3   调转到所选中的词的下一个引用位置 （必备）</span><br><span class="line">Ctrl + F4   关闭当前编辑文件</span><br><span class="line">Ctrl + F8   在 Debug 模式下，设置光标当前行为断点，如果当前已经是断点则去掉断点</span><br><span class="line">Ctrl + F9   执行 Make Project 操作</span><br><span class="line">Ctrl + F11  选中文件 / 文件夹，使用助记符设定 / 取消书签 （必备）</span><br><span class="line">Ctrl + F12  弹出当前文件结构层，可以在弹出的层上直接输入，进行筛选</span><br><span class="line">Ctrl + Tab  编辑窗口切换，如果在切换的过程又加按上 delete，则是关闭对应选中的窗口</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">Ctrl + End  跳到文件尾</span><br><span class="line">Ctrl + Home 跳到文件头</span><br><span class="line">Ctrl + Space       基础代码补全，默认在 Windows 系统上被输入法占用，需要进行修改，建议修改为 Ctrl +逗号 （必备）</span><br><span class="line">Ctrl + Delete      删除光标后面的单词或是中文句 （必备）</span><br><span class="line">Ctrl +BackSpace    删除光标前面的单词或是中文句 （必备）</span><br><span class="line">Ctrl +<span class="number">1</span>,<span class="number">2</span>,<span class="number">3.</span>.<span class="number">.9</span>    定位到对应数值的书签位置 （必备）</span><br><span class="line">Ctrl + 左键单击     在打开的文件标题上，弹出该文件路径 （必备）</span><br><span class="line">Ctrl + 光标定位按   Ctrl 不要松开，会显示光标所在的类信息摘要</span><br><span class="line">Ctrl + 左方向键     光标跳转到当前单词 / 中文句的左侧开头位置 （必备）</span><br><span class="line">Ctrl + 右方向键     光标跳转到当前单词 / 中文句的右侧开头位置 （必备）</span><br><span class="line">Ctrl + 前方向键     等效于鼠标滚轮向前效果 （必备）</span><br><span class="line">Ctrl + 后方向键     等效于鼠标滚轮向后效果 （必备）</span><br></pre></td></tr></table></figure><h2 id="Alt-快捷键"><a href="#Alt-快捷键" class="headerlink" title="Alt 快捷键"></a>Alt 快捷键</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">Alt + `   显示版本控制常用操作菜单弹出层 （必备）</span><br><span class="line">Alt + Q   弹出一个提示，显示当前类的声明 / 上下文信息</span><br><span class="line">Alt + F1  显示当前文件选择目标弹出层，弹出层中有很多目标可以进行选择 （必备）</span><br><span class="line">Alt + F2  对于前面页面，显示各类浏览器打开目标选择弹出层</span><br><span class="line">Alt + F3  选中文本，逐个往下查找相同文本，并高亮显示</span><br><span class="line">Alt + F7  查找光标所在的方法 / 变量 / 类被调用的地方</span><br><span class="line">Alt + F8  在 Debug 的状态下，选中对象，弹出可输入计算表达式调试框，查看该输入内容的调试结果</span><br><span class="line">Alt + Home   定位 / 显示到当前文件的 Navigation Bar</span><br><span class="line">Alt + Enter  IntelliJ IDEA 根据光标所在问题，提供快速修复选择，光标放在的位置不同提示的结果也不同 （必备）</span><br><span class="line">Alt + Insert 代码自动生成，如生成对象的 set / get 方法，构造函数，toString() 等 （必备）</span><br><span class="line">Alt + 左方向键     切换当前已打开的窗口中的子视图，比如 Debug 窗口中有 Output、Debugger 等子视图，用此快捷键就可以在子视图中切换 （必备）</span><br><span class="line">Alt + 右方向键     按切换当前已打开的窗口中的子视图，比如 Debug 窗口中有 Output、Debugger 等子视图，用此快捷键就可以在子视图中切换 （必备）</span><br><span class="line">Alt + 前方向键     当前光标跳转到当前文件的前一个方法名位置 （必备）</span><br><span class="line">Alt + 后方向键     当前光标跳转到当前文件的后一个方法名位置 （必备）</span><br><span class="line">Alt +<span class="number">1</span>,<span class="number">2</span>,<span class="number">3.</span>.<span class="number">.9</span>    显示对应数值的选项卡，其中 <span class="number">1</span> 是 Project 用得最多 （必备）</span><br></pre></td></tr></table></figure><h2 id="Shift-快捷键"><a href="#Shift-快捷键" class="headerlink" title="Shift 快捷键"></a>Shift 快捷键</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">Shift + F1   如果有外部文档可以连接外部文档</span><br><span class="line">Shift + F2   跳转到上一个高亮错误 或 警告位置</span><br><span class="line">Shift + F3   在查找模式下，查找匹配上一个</span><br><span class="line">Shift + F4   对当前打开的文件，使用新 Windows 窗口打开，旧窗口保留</span><br><span class="line">Shift + F6   对文件 / 文件夹 重命名</span><br><span class="line">Shift + F7   在 Debug 模式下，智能步入。断点所在行上有多个方法调用，会弹出进入哪个方法</span><br><span class="line">Shift + F8   在 Debug 模式下，跳出，表现出来的效果跟 F9 一样</span><br><span class="line">Shift + F9   等效于点击工具栏的 Debug 按钮</span><br><span class="line">Shift + F10  等效于点击工具栏的 Run 按钮</span><br><span class="line">Shift + F11  弹出书签显示层 （必备）</span><br><span class="line">Shift + Tab    取消缩进 （必备）</span><br><span class="line">Shift + ESC    隐藏当前 或 最后一个激活的工具窗口</span><br><span class="line">Shift + End    选中光标到当前行尾位置</span><br><span class="line">Shift + Home   选中光标到当前行头位置</span><br><span class="line">Shift + Enter    开始新一行。光标所在行下空出一行，光标定位到新行位置 （必备）</span><br><span class="line">Shift + 左键单击      在打开的文件名上按此快捷键，可以关闭当前打开文件 （必备）</span><br><span class="line">Shift + 滚轮前后滚动   当前文件的横向滚动轴滚动 （必备）</span><br></pre></td></tr></table></figure><h2 id="Ctrl-Alt-快捷键"><a href="#Ctrl-Alt-快捷键" class="headerlink" title="Ctrl + Alt 快捷键"></a>Ctrl + Alt 快捷键</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Ctrl + Alt + L   格式化代码，可以对当前文件和整个包目录使用 （必备）</span><br><span class="line">Ctrl + Alt + O   优化导入的类，可以对当前文件和整个包目录使用 （必备）</span><br><span class="line">Ctrl + Alt + I   光标所在行 或 选中部分进行自动代码缩进，有点类似格式化</span><br><span class="line">Ctrl + Alt + T   对选中的代码弹出环绕选项弹出层 （必备）</span><br><span class="line">Ctrl + Alt + J   弹出模板选择窗口，将选定的代码加入动态模板中</span><br><span class="line">Ctrl + Alt + H   调用层次</span><br><span class="line">Ctrl + Alt + B   在某个调用的方法名上使用会跳到具体的实现处，可以跳过接口</span><br><span class="line">Ctrl + Alt + V   快速引进变量</span><br><span class="line">Ctrl + Alt + Y   同步、刷新</span><br><span class="line">Ctrl + Alt + S   打开 IntelliJ IDEA 系统设置 （必备）</span><br><span class="line">Ctrl + Alt + F7  显示使用的地方。寻找被该类或是变量被调用的地方，用弹出框的方式找出来</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Ctrl + Alt + F11 切换全屏模式</span><br><span class="line">Ctrl + Alt + Enter   光标所在行上空出一行，光标定位到新行 （必备）</span><br><span class="line">Ctrl + Alt + Home    弹出跟当前文件有关联的文件弹出层</span><br><span class="line">Ctrl + Alt + Space   类名自动完成</span><br><span class="line">Ctrl + Alt + 左方向键    退回到上一个操作的地方 （必备）</span><br><span class="line">Ctrl + Alt + 右方向键    前进到上一个操作的地方 （必备）</span><br><span class="line">Ctrl + Alt + 前方向键    在查找模式下，跳到上个查找的文件</span><br><span class="line">Ctrl + Alt + 后方向键    在查找模式下，跳到下个查找的文件</span><br></pre></td></tr></table></figure><h2 id="Ctrl-Shift-快捷键"><a href="#Ctrl-Shift-快捷键" class="headerlink" title="Ctrl + Shift 快捷键"></a>Ctrl + Shift 快捷键</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Ctrl + Shift + F  根据输入内容查找整个项目 或 指定目录内文件 （必备）</span><br><span class="line">Ctrl + Shift + R  根据输入内容替换对应内容，范围为整个项目 或 指定目录内文件 （必备）</span><br><span class="line">Ctrl + Shift + J  自动将下一行合并到当前行末尾 （必备）</span><br><span class="line">Ctrl + Shift + Z  取消撤销 （必备）</span><br><span class="line">Ctrl + Shift + W  递进式取消选择代码块。可选中光标所在的单词或段落，连续按会在原有选中的基础上再扩展取消选中范围 （必备）</span><br><span class="line">Ctrl + Shift + N  通过文件名定位 / 打开文件 / 目录，打开目录需要在输入的内容后面多加一个正斜杠 （必备）</span><br><span class="line">Ctrl + Shift + U  对选中的代码进行大 / 小写轮流转换 （必备）</span><br><span class="line">Ctrl + Shift + T  对当前类生成单元测试类，如果已经存在的单元测试类则可以进行选择 （必备）</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">Ctrl + Shift + C  复制当前文件磁盘路径到剪贴板 （必备）</span><br><span class="line">Ctrl + Shift + V  弹出缓存的最近拷贝的内容管理器弹出层</span><br><span class="line">Ctrl + Shift + E  显示最近修改的文件列表的弹出层</span><br><span class="line">Ctrl + Shift + H  显示方法层次结构</span><br><span class="line">Ctrl + Shift + B  跳转到类型声明处 （必备）</span><br><span class="line">Ctrl + Shift + I  快速查看光标所在的方法 或 类的定义</span><br><span class="line">Ctrl + Shift + A  查找动作 / 设置</span><br><span class="line">Ctrl + Shift + /  代码块注释 （必备）</span><br><span class="line">Ctrl + Shift + [  选中从光标所在位置到它的顶部中括号位置 （必备）</span><br><span class="line">Ctrl + Shift + ]  选中从光标所在位置到它的底部中括号位置 （必备）</span><br><span class="line">Ctrl + Shift + +  展开所有代码 （必备）</span><br><span class="line">Ctrl + Shift + -  折叠所有代码 （必备）</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Ctrl + Shift + F7    高亮显示所有该选中文本，按 Esc 高亮消失 （必备）</span><br><span class="line">Ctrl + Shift + F8    在 Debug 模式下，指定断点进入条件</span><br><span class="line">Ctrl + Shift + F9    编译选中的文件 / 包 / Module</span><br><span class="line">Ctrl + Shift + F12   编辑器最大化 （必备）</span><br><span class="line">Ctrl + Shift + Space 智能代码提示</span><br><span class="line">Ctrl + Shift + Enter 自动结束代码，行末自动添加分号 （必备）</span><br><span class="line">Ctrl + Shift +Backspace  退回到上次修改的地方 （必备）</span><br><span class="line">Ctrl + Shift +<span class="number">1</span>,<span class="number">2</span>,<span class="number">3.</span>.<span class="number">.9</span>  快速添加指定数值的书签 （必备）</span><br><span class="line">Ctrl + Shift + 左键单击   把光标放在某个类变量上，按此快捷键可以直接定位到该类中 （必备）</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Ctrl + Shift + 左方向键    在代码文件上，光标跳转到当前单词 / 中文句的左侧开头位置，同时选中该单词 / 中文句（必备） </span><br><span class="line">Ctrl + Shift + 右方向键    在代码文件上，光标跳转到当前单词 / 中文句的右侧开头位置，同时选中该单词 / 中文句（必备）</span><br><span class="line">Ctrl + Shift + 前方向键    光标放在方法名上，将方法移动到上一个方法前面，调整方法排序 （必备）</span><br><span class="line">Ctrl + Shift + 后方向键    光标放在方法名上，将方法移动到下一个方法前面，调整方法排序 （必备）</span><br></pre></td></tr></table></figure><h2 id="Alt-Shift-快捷键"><a href="#Alt-Shift-快捷键" class="headerlink" title="Alt + Shift 快捷键"></a>Alt + Shift 快捷键</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Alt + Shift + N     选择 / 添加 task （必备）</span><br><span class="line">Alt + Shift + F     显示添加到收藏夹弹出层 / 添加到收藏夹</span><br><span class="line">Alt + Shift + C     查看最近操作项目的变化情况列表</span><br><span class="line">Alt + Shift + I     查看项目当前文件</span><br><span class="line">Alt + Shift + F7在  Debug 模式下，下一步，进入当前方法体内，如果方法体还有方法，则会进入该内嵌的方法中，依此循环进入</span><br><span class="line">Alt + Shift + F9    弹出 Debug 的可选择菜单</span><br><span class="line">Alt + Shift + F10   弹出 Run 的可选择菜单</span><br><span class="line">Alt + Shift + 左键双击  选择被双击的单词 / 中文句，按住不放，可以同时选择其他单词 / 中文句 （必备）</span><br><span class="line">Alt + Shift + 前方向键  移动光标所在行向上移动 （必备）</span><br><span class="line">Alt + Shift + 后方向键  移动光标所在行向下移动 （必备）</span><br></pre></td></tr></table></figure><h2 id="Ctrl-Shift-Alt-快捷键"><a href="#Ctrl-Shift-Alt-快捷键" class="headerlink" title="Ctrl + Shift + Alt 快捷键"></a>Ctrl + Shift + Alt 快捷键</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Ctrl + Shift + Alt + V   无格式黏贴 （必备）</span><br><span class="line">Ctrl + Shift + Alt + N   前往指定的变量 / 方法</span><br><span class="line">Ctrl + Shift + Alt + S   打开当前项目设置 （必备）</span><br><span class="line">Ctrl + Shift + Alt + C   复制参考信息</span><br></pre></td></tr></table></figure><h2 id="其他快捷键"><a href="#其他快捷键" class="headerlink" title="其他快捷键"></a>其他快捷键</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">F2   跳转到下一个高亮错误 或 警告位置 （必备）</span><br><span class="line">F3   在查找模式下，定位到下一个匹配处</span><br><span class="line">F4   编辑源 （必备）</span><br><span class="line">F7   在 Debug 模式下，进入下一步，如果当前行断点是一个方法，则进入当前方法体内，如果该方法体还有方法，则不会进入该内嵌的方法中</span><br><span class="line">F8   在 Debug 模式下，进入下一步，如果当前行断点是一个方法，则不进入当前方法体内</span><br><span class="line">F9   在 Debug 模式下，恢复程序运行，但是如果该断点下面代码还有断点则停在下一个断点上</span><br><span class="line">F11  添加书签 （必备）</span><br><span class="line">F12  回到前一个工具窗口 （必备）</span><br><span class="line">Tab缩进 （必备）</span><br><span class="line">ESC     从工具窗口进入代码文件窗口 （必备）</span><br><span class="line">连按两次Shift  弹出 Search Everywhere 弹出层</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">说 IDEA 对新手来说难，可能其中一个原因就是快捷键组合多而且复杂但是它也很全，基本所有功能都可以通过快捷键来完成，可以这么说，如果你掌握了所有 IDEA 的快捷键使用</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="IntelliJ IDEA" scheme="https://blog.imzjw.cn/tags/IntelliJ-IDEA/"/>
    
  </entry>
  
  <entry>
    <title>RabbitMQ安装</title>
    <link href="https://blog.imzjw.cn/posts/64b1/"/>
    <id>https://blog.imzjw.cn/posts/64b1/</id>
    <published>2020-06-11T01:23:00.000Z</published>
    <updated>2020-06-11T01:23:00.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="安装-Socat"><a href="#安装-Socat" class="headerlink" title="安装 Socat"></a>安装 Socat</h2><p>在线安装依赖环境：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">yum install gcc</span><br><span class="line"></span><br><span class="line">yum install socat</span><br></pre></td></tr></table></figure><h2 id="安装-Erlang"><a href="#安装-Erlang" class="headerlink" title="安装 Erlang"></a>安装 Erlang</h2><p>Erlang 官网下载真的慢，这里提供下载</p><div class="btns rounded grid5">            <a class="button" href='https://garvey.lanzoux.com/b0ejrzaja' title='下载地址'><i class='fas fa-download'></i>下载地址</a>          </div><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> /rabbitmq &amp;&amp; <span class="built_in">cd</span> /rabbitmq</span><br><span class="line"></span><br><span class="line"><span class="comment"># 上传 erlang-22.0.7-1.el7.x86_64.rpm 安装包</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装</span></span><br><span class="line">rpm -ivh erlang-22.0.7-1.el7.x86_64.rpm</span><br></pre></td></tr></table></figure><h2 id="安装-RabbitMQ"><a href="#安装-RabbitMQ" class="headerlink" title="安装 RabbitMQ"></a>安装 RabbitMQ</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /rabbitmq</span><br><span class="line"></span><br><span class="line"><span class="comment"># 上传 rabbitmq-server-3.7.17-1.el7.noarch.rpm 安装包</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装</span></span><br><span class="line">rpm -ivh rabbitmq-server-3.7.17-1.el7.noarch.rpm</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/64b1/20201012144300.webp" alt="img"></p><h2 id="开启管理界面及配置"><a href="#开启管理界面及配置" class="headerlink" title="开启管理界面及配置"></a>开启管理界面及配置</h2><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 开启管理界面</span></span><br><span class="line">rabbitmq-plugins <span class="built_in">enable</span> rabbitmq_management</span><br><span class="line"></span><br><span class="line"><span class="comment"># 配置远程可使用guest登录mq</span></span><br><span class="line"><span class="built_in">cd</span> /usr/share/doc/rabbitmq-server-3.7.17</span><br><span class="line"></span><br><span class="line"><span class="built_in">cp</span> rabbitmq.config.example /etc/rabbitmq/rabbitmq.config</span><br><span class="line"></span><br><span class="line"><span class="comment"># 修改配置文件</span></span><br><span class="line">vim /etc/rabbitmq/rabbitmq.config</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/64b1/20201012144352.webp" alt="img"></p><p>修改 <code>/etc/rabbitmq/rabbitmq.config</code> 配置文件</p><ul><li><p>修改之前</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/64b1/update.webp" alt="img"></p></li><li><p>修改之后</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/64b1/update2.webp" alt="img"></p></li></ul><h2 id="启动"><a href="#启动" class="headerlink" title="启动"></a>启动</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">centos6用这个命令</span></span><br><span class="line">/sbin/service rabbitmq-server restart</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">centos7用这个命令</span></span><br><span class="line">systemctl start rabbitmq-server</span><br></pre></td></tr></table></figure><h2 id="配置虚拟主机及用户"><a href="#配置虚拟主机及用户" class="headerlink" title="配置虚拟主机及用户"></a>配置虚拟主机及用户</h2><h3 id="用户角色"><a href="#用户角色" class="headerlink" title="用户角色"></a>用户角色</h3><p>RabbitMQ 在安装好后，可以访问 <code>http://ip地址:15672</code> ；其自带了 <code>guest</code> / <code>guest</code> 的用户名和密码；如果需要创建自定义用户；那么也可以登录管理界面后，如下操作：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/64b1/kk.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/64b1/yy.webp" alt="img"></p><h3 id="角色说明"><a href="#角色说明" class="headerlink" title="角色说明"></a>角色说明</h3><ol><li>超级管理员(administrator)<ul><li>可登陆管理控制台，可查看所有的信息，并且可以对用户，策略(policy)进行操作。</li></ul></li><li>监控者(monitoring)<ul><li>可登陆管理控制台，同时可以查看rabbitmq节点的相关信息(进程数，内存使用情况，磁盘使用情况等)</li></ul></li><li>策略制定者(policymaker)<ul><li>可登陆管理控制台, 同时可以对policy进行管理。但无法查看节点的相关信息(上图红框标识的部分)。</li></ul></li><li>普通管理者(management)<ul><li>仅可登陆管理控制台，无法看到节点信息，也无法对策略进行管理。</li></ul></li><li>其他<ul><li>无法登陆管理控制台，通常就是普通的生产者和消费者。</li></ul></li></ol><h3 id="Virtual-Hosts配置"><a href="#Virtual-Hosts配置" class="headerlink" title="Virtual Hosts配置"></a>Virtual Hosts配置</h3><p>像 MySQL 拥有数据库的概念并且可以指定用户对库和表等操作的权限。</p><p>RabbitMQ 也有类似的权限管理，在 RabbitMQ 中可以虚拟消息服务器 Virtual Host</p><p>每个 Virtual Hosts 相当于一个相对独立的 RabbitMQ 服务器，每个 VirtualHost 之间是相互隔离的。</p><p>exchange、queue、message 不能互通。 相当于 MySQL 的 db。Virtual Name 一般以 / 开头。</p><ol><li><p>创建Virtual Hosts</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/64b1/Hosts.webp" alt="img"></p></li><li><p>设置Virtual Hosts权限</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/64b1/ll.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/64b1/bb.webp" alt="img"></p></li></ol>]]></content>
    
    
    <summary type="html">安装 Socat，在线安装依赖环境：yum install gcc，yum install socat，安装 Erlang，erlang 官网下载真的慢，这里提供下载...</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="RabbitMQ" scheme="https://blog.imzjw.cn/tags/RabbitMQ/"/>
    
  </entry>
  
  <entry>
    <title>个人常用的在线工具网站</title>
    <link href="https://blog.imzjw.cn/posts/4b69/"/>
    <id>https://blog.imzjw.cn/posts/4b69/</id>
    <published>2020-06-10T14:49:47.000Z</published>
    <updated>2020-06-10T14:49:47.000Z</updated>
    
    <content type="html"><![CDATA[<div class="note success flat"><p>简单整理了一下自己日常经常使用的工具网站，分享给小伙伴们！</p></div><h2 id="奶牛快传"><a href="#奶牛快传" class="headerlink" title="奶牛快传"></a>奶牛快传</h2><p><a href="https://cowtransfer.com/">https://cowtransfer.com/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200801120657.webp" alt="img"></p><p>最近开始使用的一款网盘工具，和百度网盘类似，不过没有下载速度的限制</p><p>并且可以支持自定义分享文件的下载次数（需要开会员）</p><p>还有一点让我觉得比较舒服的是，你给别人分享文件，别人无需登录就可以直接下载。</p><p>缺点也比较明显，免费用户的容量只有 5g 并且单次传输上限是 2g，所以，可能需要付费才能更好的使用。</p><h2 id="docsmall压缩"><a href="#docsmall压缩" class="headerlink" title="docsmall压缩"></a>docsmall压缩</h2><p><a href="https://docsmall.com/">https://docsmall.com/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200610225933.webp" alt="img"></p><div class="note info flat"><p>我经常用来压缩图片、GIF、PDF。并且还支持 PDF 合并和分割</p></div><h2 id="创客贴"><a href="#创客贴" class="headerlink" title="创客贴"></a>创客贴</h2><p><strong>平面设计作图神器</strong></p><p><a href="https://www.chuangkit.com/">https://www.chuangkit.com/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200610230153.webp" alt="img"></p><div class="note info flat"><p>通过这个网站你可以制作好看的海报、简历、新媒体文章的首页图等等，这个网站甚至还有很多免费且好看的 PPT插件，简直是神器。</p></div><h2 id="Dimmy-club"><a href="#Dimmy-club" class="headerlink" title="Dimmy.club"></a>Dimmy.club</h2><p><strong>手机电脑等设备的展示模型</strong></p><p><a href="https://dimmy.club/">https://dimmy.club/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200610230256.webp" alt="img"></p><div class="note info flat"><p>可以让你的图片放在电脑、手机、ipad 等模型中展示，大大提升了图片的档次。</p></div><h2 id="BrowserFrame"><a href="#BrowserFrame" class="headerlink" title="BrowserFrame"></a>BrowserFrame</h2><p><strong>浏览器展示模型</strong></p><p><a href="https://browserframe.com/">https://browserframe.com/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200610230557.webp" alt="img"></p><h2 id="Flourish"><a href="#Flourish" class="headerlink" title="Flourish"></a>Flourish</h2><p><strong>数据可视化</strong></p><p><a href="https://flourish.studio/">https://flourish.studio/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200610230656.webp" alt="img"></p><div class="note info flat"><p>通过这个网站，你可以快速地把表格数据转换为各种各样好看的图表，并且还支持动态可视化。</p></div><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/1726411cd6ca3d2e.gif" alt="img"></p><h2 id="PDF派"><a href="#PDF派" class="headerlink" title="PDF派"></a>PDF派</h2><p><strong>20个免费好用的PDF在线工具</strong></p><p><a href="https://www.pdfpai.com/">https://www.pdfpai.com/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200610230825.webp" alt="img"></p><div class="note info flat"><p>PDF 在线工具挺多的，PDF 派是我最喜欢的一个，功能强大稳定。</p></div><h2 id="小码短连接"><a href="#小码短连接" class="headerlink" title="小码短连接"></a>小码短连接</h2><p><strong>简单易用的渠道短链接统计工具</strong></p><p><a href="https://xiaomark.com/">https://xiaomark.com/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/xiaomark.webp" alt="img"></p><div class="note info flat"><p>非常好用的长链接转短链接工具，能够让链接看起来更简洁。并且，转换为短链接之后，还能在后台监测访问数据，如访问次数、访问人数。</p></div><h2 id="Kapwing"><a href="#Kapwing" class="headerlink" title="Kapwing"></a>Kapwing</h2><p><strong>一个用于创建图像，视频和GIF的协作平台</strong></p><p><a href="https://www.kapwing.com/">https://www.kapwing.com/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200610230948.webp" alt="img"></p><div class="note info flat"><p>Kapwing 是一个在线视频编辑网站，集成了很多在线小工具</p></div><h2 id="removebg"><a href="#removebg" class="headerlink" title="removebg"></a>removebg</h2><p><strong>抠图神器</strong></p><p><a href="https://www.remove.bg/zh">https://www.remove.bg/zh</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200610231025.webp" alt="img"></p><div class="note info flat"><p>抠图神器，绝对的神器！</p></div><h2 id="今日热榜"><a href="#今日热榜" class="headerlink" title="今日热榜"></a>今日热榜</h2><p><a href="https://tophub.today/">https://tophub.today/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200610231130.webp" alt="img"></p><div class="note info flat"><p>今日热榜提供各站热榜聚合：微信、今日头条、百度、知乎、V2EX、微博、贴吧、豆瓣、天涯、虎扑、Github、抖音…追踪全网热点、简单高效阅读。</p></div><h2 id="Apkpure"><a href="#Apkpure" class="headerlink" title="Apkpure"></a>Apkpure</h2><p>安卓安装包下载，其实如果你玩 tg 的话，tg 里有个 apk 下载的 Bot</p><p><a href="https://apkpure.com/cn/">https://apkpure.com/cn/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200610231219.webp" alt="img"></p><h2 id="crx4chrome"><a href="#crx4chrome" class="headerlink" title="crx4chrome"></a>crx4chrome</h2><p>国内下载 Chrome 浏览器插件</p><p><a href="https://www.crx4chrome.com/">https://www.crx4chrome.com/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/crx4chrome.webp" alt="img"></p><div class="note info flat"><p>如果你无法访问谷歌商店的话，可以通过这个网站来下载你想要的 Chrome 浏览器插件</p></div><h2 id="ProcessOn"><a href="#ProcessOn" class="headerlink" title="ProcessOn"></a>ProcessOn</h2><p><a href="https://www.processon.com/">https://www.processon.com/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200610231332.webp" alt="img"></p><div class="note info flat"><p>画图工具，支持流程图、思维导图、原型图、UML、网络拓扑图、组织结构图等。我老师经常用</p></div><h2 id="draw-io"><a href="#draw-io" class="headerlink" title="draw.io"></a>draw.io</h2><p><strong>又一个画图工具</strong></p><p><a href="https://www.draw.io/">https://www.draw.io/</a></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200610231359.webp" alt="img"></p><div class="note info flat"><p>这个画图工具，不光有在线版还有电脑版，并且可以将文件保存到多个位置。</p></div><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/4b69/20200610231421.webp" alt="img"></p><h2 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h2><ol><li><a href="https://carbon.now.sh/">Carbon</a> : 生成漂亮的代码图片。</li><li><a href="https://excalidraw.com/">excalidraw</a> ：简洁大方的在线画图工具。</li><li><a href="https://mdnice.com/">mdnice</a>：支持自定义样式的 Markdown 编辑器。支持微信公众号、知乎和稀土掘金的排版。</li><li>…</li></ol>]]></content>
    
    
    <summary type="html">简单整理了一下自己日常经常使用的工具网站，分享给小伙伴们！奶牛快传-最近开始使用的一款网盘工具，和百度网盘类似，不过没有下载速度的限制，并且可以支持自定义分享文件的下载次数（需要开会员）</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="在线网站" scheme="https://blog.imzjw.cn/tags/%E5%9C%A8%E7%BA%BF%E7%BD%91%E7%AB%99/"/>
    
  </entry>
  
  <entry>
    <title>RabbitMQ（二）</title>
    <link href="https://blog.imzjw.cn/posts/530a/"/>
    <id>https://blog.imzjw.cn/posts/530a/</id>
    <published>2020-06-10T14:00:00.000Z</published>
    <updated>2020-06-10T14:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="使用-RabbitMQ-传递对象"><a href="#使用-RabbitMQ-传递对象" class="headerlink" title="使用 RabbitMQ 传递对象"></a>使用 RabbitMQ 传递对象</h2><div class="note success flat"><p>RabbitMQ 是消息队列，发送和接收的都是字符串/字节数组类型的消息</p></div><h3 id="使用序列化对象"><a href="#使用序列化对象" class="headerlink" title="使用序列化对象"></a>使用序列化对象</h3><p><strong>要求：</strong></p><ol><li>传递的对象实现序列化接口</li><li>传递的对象的包名、类名、属性名必须一致</li></ol><ul><li><p>消息提供者</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> GarveyZhong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2020/6/10 22:06</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MQService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> AmqpTemplate amqpTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sendGoodsToMq</span><span class="params">(Goods goods)</span> &#123;</span><br><span class="line">        <span class="comment">// 消息队列可以发送 字符串、字节数组、序列化对象</span></span><br><span class="line">        amqpTemplate.convertAndSend(<span class="string">&quot;&quot;</span>, <span class="string">&quot;queue1&quot;</span>, goods);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>消息消费者</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> GarveyZhong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2020/6/10 22:06</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@RabbitListener(queues = &quot;queue1&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReceiveService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RabbitHandler</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receiveMsg</span><span class="params">(Goods goods)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;Goods---&quot;</span> + goods);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul><h3 id="使用序列化字节数组"><a href="#使用序列化字节数组" class="headerlink" title="使用序列化字节数组"></a>使用序列化字节数组</h3><p><strong>要求：</strong></p><ol><li>传递的对象实现序列化接口</li><li>传递的对象的包名、类名、属性名必须一致</li></ol><ul><li><p>消息提供者</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MQService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> AmqpTemplate amqpTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sendGoodsToMq</span><span class="params">(Goods goods)</span> &#123;</span><br><span class="line">        <span class="comment">// 消息队列可以发送 字符串、字节数组、序列化对象</span></span><br><span class="line">        <span class="type">byte</span>[] bytes = SerializationUtils.serialize(goods);</span><br><span class="line">        amqpTemplate.convertAndSend(<span class="string">&quot;&quot;</span>, <span class="string">&quot;queue1&quot;</span>, bytes);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>消息消费者</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@RabbitListener(queues = &quot;queue1&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReceiveService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RabbitHandler</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receiveMsg</span><span class="params">(<span class="type">byte</span>[] bs)</span> &#123;</span><br><span class="line">        <span class="type">Object</span> <span class="variable">goods</span> <span class="operator">=</span> SerializationUtils.deserialize(bs);</span><br><span class="line">        System.out.println(<span class="string">&quot;byte[]---&quot;</span> + goods);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul><h3 id="使用JSON字符串传递"><a href="#使用JSON字符串传递" class="headerlink" title="使用JSON字符串传递"></a>使用JSON字符串传递</h3><div class="note warning flat"><p>要求：对象的属性名一致</p></div><ul><li><p>消息提供者</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MQService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> AmqpTemplate amqpTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sendGoodsToMq</span><span class="params">(Goods goods)</span> <span class="keyword">throws</span> JsonProcessingException &#123;</span><br><span class="line">        <span class="comment">// 消息队列可以发送 字符串、字节数组、序列化对象</span></span><br><span class="line">        <span class="type">ObjectMapper</span> <span class="variable">objectMapper</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ObjectMapper</span>();</span><br><span class="line">        <span class="type">String</span> <span class="variable">msg</span> <span class="operator">=</span> objectMapper.writeValueAsString(goods);</span><br><span class="line">        amqpTemplate.convertAndSend(<span class="string">&quot;&quot;</span>, <span class="string">&quot;queue1&quot;</span>, msg);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>消息消费者</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@RabbitListener(queues = &quot;queue1&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReceiveService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RabbitHandler</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receiveMsg</span><span class="params">(String msg)</span> <span class="keyword">throws</span> JsonProcessingException &#123;</span><br><span class="line">        <span class="type">ObjectMapper</span> <span class="variable">objectMapper</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ObjectMapper</span>();</span><br><span class="line">        <span class="type">Goods</span> <span class="variable">goods</span> <span class="operator">=</span> objectMapper.readValue(msg, Goods.class);</span><br><span class="line">        System.out.println(<span class="string">&quot;String---&quot;</span> + msg);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul><h2 id="基于-Java-的交换机与队列创建"><a href="#基于-Java-的交换机与队列创建" class="headerlink" title="基于 Java 的交换机与队列创建"></a>基于 Java 的交换机与队列创建</h2><div class="note info flat"><p>我们使用消息队列，消息队列和交换机可以通过管理系统完成创建，也可以在应用程序中通过 Java 代码来完成创建</p></div><h3 id="Maven-项目交换机及队列创建"><a href="#Maven-项目交换机及队列创建" class="headerlink" title="Maven 项目交换机及队列创建"></a>Maven 项目交换机及队列创建</h3><ul><li><p>使用 Java 代码新建队列</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1.定义队列 (使用Java代码在MQ中新建一个队列)</span></span><br><span class="line"><span class="comment">// 参数1：定义的队列名称</span></span><br><span class="line"><span class="comment">// 参数2：队列中的数据是否持久化（如果选择了持久化）</span></span><br><span class="line"><span class="comment">// 参数3: 是否排外（当前队列是否为当前连接私有）</span></span><br><span class="line"><span class="comment">// 参数4：自动删除（当此队列的连接数为0时，此队列会销毁（无论队列中是否还有数据））</span></span><br><span class="line"><span class="comment">// 参数5：设置当前队列的参数</span></span><br><span class="line">channel.queueDeclare(<span class="string">&quot;queue7&quot;</span>, <span class="literal">false</span>, <span class="literal">false</span>, <span class="literal">false</span>, <span class="literal">null</span>);</span><br></pre></td></tr></table></figure></li><li><p>新建交换机</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 定义一个“订阅交换机”</span></span><br><span class="line">channel.exchangeDeclare(<span class="string">&quot;ex3&quot;</span>, BuiltinExchangeType.FANOUT);</span><br><span class="line"><span class="comment">// 定义一个“路由交换机”</span></span><br><span class="line">channel.exchangeDeclare(<span class="string">&quot;ex4&quot;</span>, BuiltinExchangeType.DIRECT);</span><br></pre></td></tr></table></figure></li><li><p>绑定队列到交换机</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 绑定队列</span></span><br><span class="line"><span class="comment">// 参数1：队列名称</span></span><br><span class="line"><span class="comment">// 参数2：目标交换机</span></span><br><span class="line"><span class="comment">// 参数3：如果绑定订阅交换机参数为&quot;&quot;,如果绑定路由交换机则表示设置队列的key</span></span><br><span class="line">channel.queueBind(<span class="string">&quot;queue7&quot;</span>, <span class="string">&quot;ex4&quot;</span>, <span class="string">&quot;k1&quot;</span>);</span><br><span class="line">channel.queueBind(<span class="string">&quot;queue8&quot;</span>, <span class="string">&quot;ex4&quot;</span>, <span class="string">&quot;k2&quot;</span>);</span><br></pre></td></tr></table></figure></li></ul><h3 id="SpringBoot-通过配置完成队列的创建"><a href="#SpringBoot-通过配置完成队列的创建" class="headerlink" title="SpringBoot 通过配置完成队列的创建"></a>SpringBoot 通过配置完成队列的创建</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> GarveyZhong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2020/6/9 22:21</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RabbitMQConfig</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * SpringBoot 新建队列</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> Queue <span class="title function_">queue9</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Queue</span>(<span class="string">&quot;queue9&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> Queue <span class="title function_">queue10</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">Queue</span> <span class="variable">queue10</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Queue</span>(<span class="string">&quot;queue10&quot;</span>);</span><br><span class="line">        <span class="comment">// queue10.设置参数</span></span><br><span class="line">        <span class="keyword">return</span> queue10;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 声明订阅交换机</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> FanoutExchange <span class="title function_">ex5</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">FanoutExchange</span>(<span class="string">&quot;ex5&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 声明路由交换机</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> DirectExchange <span class="title function_">ex6</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">DirectExchange</span>(<span class="string">&quot;ex6&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 绑定队列</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> queue9</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> ex6</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> Binding <span class="title function_">bindingQueue9</span><span class="params">(Queue queue9, DirectExchange ex6)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> BindingBuilder.bind(queue9).to(ex6).with(<span class="string">&quot;k1&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 绑定队列</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> queue10</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> ex6</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> Binding <span class="title function_">bindingQueue10</span><span class="params">(Queue queue10, DirectExchange ex6)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> BindingBuilder.bind(queue10).to(ex6).with(<span class="string">&quot;k2&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="消息的可靠性"><a href="#消息的可靠性" class="headerlink" title="消息的可靠性"></a>消息的可靠性</h2><h3 id="RabbitMQ-事务"><a href="#RabbitMQ-事务" class="headerlink" title="RabbitMQ 事务"></a>RabbitMQ 事务</h3><div class="note danger flat"><p>当在消息发送过程中添加了事务，处理效率降低几十倍甚至上百倍</p></div><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 开启事务</span></span><br><span class="line">channel.txSelect();</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    channel.basicPublish(<span class="string">&quot;ex4&quot;</span>, <span class="string">&quot;k1&quot;</span>, <span class="literal">null</span>, msg.getBytes());</span><br><span class="line">    System.out.println(<span class="string">&quot;发送：&quot;</span> + msg);</span><br><span class="line">    <span class="comment">// 提交事务</span></span><br><span class="line">    channel.txCommit();</span><br><span class="line">&#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">    <span class="comment">// 事务回滚</span></span><br><span class="line">    channel.txRollback();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="RabbitMQ-消息确认和-return-机制"><a href="#RabbitMQ-消息确认和-return-机制" class="headerlink" title="RabbitMQ 消息确认和 return 机制"></a>RabbitMQ 消息确认和 return 机制</h3><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/530a/image-20200526154912406.webp" alt="img"></p><div class="note warning flat"><p>消息确认机制：确认消息提供者是否成功发送消息到交换机</p><p>return机制：确认消息是否成功的从交换机分发到队列</p></div><h4 id="普通-Maven-项目的消息确认"><a href="#普通-Maven-项目的消息确认" class="headerlink" title="普通 Maven 项目的消息确认"></a>普通 Maven 项目的消息确认</h4><ul><li>普通 <code>confirm</code> 方式</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1.发送消息之前开启消息确认</span></span><br><span class="line">channel.confirmSelect();</span><br><span class="line">channel.basicPublish(<span class="string">&quot;ex1&quot;</span>, <span class="string">&quot;a&quot;</span>, <span class="literal">null</span>, msg.getBytes());</span><br><span class="line"><span class="comment">// 2.接收消息确认</span></span><br><span class="line"><span class="type">boolean</span> <span class="variable">b</span> <span class="operator">=</span> channel.waitForConfirms();</span><br><span class="line">System.out.println(<span class="string">&quot;发送：&quot;</span> + (b ? <span class="string">&quot;成功&quot;</span> : <span class="string">&quot;失败&quot;</span>));</span><br></pre></td></tr></table></figure><ul><li>批量 <code>confirm</code> 方式</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1.发送消息之前开启消息确认</span></span><br><span class="line">channel.confirmSelect();</span><br><span class="line"><span class="comment">// 2.批量发送消息</span></span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">    channel.basicPublish(<span class="string">&quot;ex1&quot;</span>, <span class="string">&quot;a&quot;</span>, <span class="literal">null</span>, msg.getBytes());</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 3.接收批量消息确认：发送的所有消息中，如果有一条是失败的，则所有消息发送直接失败，抛出IO异常</span></span><br><span class="line"><span class="type">boolean</span> <span class="variable">b</span> <span class="operator">=</span> channel.waitForConfirms();</span><br></pre></td></tr></table></figure><ul><li>异步 <code>confirm</code> 方式</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 发送消息之前开启消息确认</span></span><br><span class="line">channel.confirmSelect();</span><br><span class="line"><span class="comment">// 批量发送消息</span></span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">    channel.basicPublish(<span class="string">&quot;ex1&quot;</span>, <span class="string">&quot;a&quot;</span>, <span class="literal">null</span>, msg.getBytes());</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 假如发送消息需要10s，waitForConfirms会进入阻塞状态</span></span><br><span class="line"><span class="comment">// boolean b = channel.waitForConfirms();</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用监听器异步confirm</span></span><br><span class="line">channel.addConfirmListener(<span class="keyword">new</span> <span class="title class_">ConfirmListener</span>() &#123;</span><br><span class="line">    <span class="comment">//参数1： long l  返回消息的表示</span></span><br><span class="line">    <span class="comment">//参数2： boolean b 是否为批量confirm</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handleAck</span><span class="params">(<span class="type">long</span> l, <span class="type">boolean</span> b)</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;~~~~~消息成功发送到交换机&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handleNack</span><span class="params">(<span class="type">long</span> l, <span class="type">boolean</span> b)</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;~~~~~消息发送到交换机失败&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h4 id="普通-Maven-项目的-return-机制"><a href="#普通-Maven-项目的-return-机制" class="headerlink" title="普通 Maven 项目的 return 机制"></a>普通 Maven 项目的 return 机制</h4><ul><li>添加 return 监听器</li><li>发送消息是指定第三个参数为 true</li><li>由于监听器监听是异步处理，所以在消息发送之后不能关闭 channel</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">msg</span> <span class="operator">=</span> <span class="string">&quot;Hello RabbitMQ!&quot;</span>;</span><br><span class="line"><span class="comment">// 相当于JDBC操作的数据库连接</span></span><br><span class="line"><span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> ConnectionUtil.getConnection();</span><br><span class="line"><span class="comment">// 相当于JDBC操作的statement</span></span><br><span class="line"><span class="type">Channel</span> <span class="variable">channel</span> <span class="operator">=</span> connection.createChannel();</span><br><span class="line"></span><br><span class="line"><span class="comment">// return机制，监控交换机是否将消息分发到队列</span></span><br><span class="line">channel.addReturnListener(<span class="keyword">new</span> <span class="title class_">ReturnListener</span>() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handleReturn</span><span class="params">(<span class="type">int</span> replyCode, String replyText, String exchange, String routingKey, AMQP.BasicProperties properties, <span class="type">byte</span>[] body)</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="comment">// 如果交换机分发消息到队列失败，则会执行此方法（用来处理交换机分发消息到队列失败的情况）</span></span><br><span class="line">        <span class="comment">// 标识</span></span><br><span class="line">        System.out.println(<span class="string">&quot;唯一标识：&quot;</span> + replyCode);</span><br><span class="line">        <span class="comment">// 忘了</span></span><br><span class="line">        System.out.println(<span class="string">&quot;replyText == &quot;</span> + replyText);</span><br><span class="line">        <span class="comment">// 交换机名</span></span><br><span class="line">        System.out.println(<span class="string">&quot;exchange == &quot;</span> + exchange);</span><br><span class="line">        <span class="comment">// 交换机对应队列的key</span></span><br><span class="line">        System.out.println(<span class="string">&quot;routingKey == &quot;</span> + routingKey);</span><br><span class="line">        <span class="comment">// 发送的消息</span></span><br><span class="line">        System.out.println(<span class="string">&quot;body == &quot;</span> + <span class="keyword">new</span> <span class="title class_">String</span>(body));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">//发送消息</span></span><br><span class="line"><span class="comment">// channel.basicPublish(&quot;ex4&quot;, &quot;g&quot;, null, msg.getBytes());</span></span><br><span class="line"><span class="comment">// 不仅开启消息确认，还开启了return机制</span></span><br><span class="line">channel.basicPublish(<span class="string">&quot;ex4&quot;</span>, <span class="string">&quot;g&quot;</span>, <span class="literal">true</span>, <span class="literal">null</span>, msg.getBytes());</span><br></pre></td></tr></table></figure><h3 id="在-SpringBoot-实现消息确认与-return-监听"><a href="#在-SpringBoot-实现消息确认与-return-监听" class="headerlink" title="在 SpringBoot 实现消息确认与 return 监听"></a>在 SpringBoot 实现消息确认与 return 监听</h3><p>配置 application.yml, 开启消息确认和 return 监听</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">rabbitmq:</span></span><br><span class="line">    <span class="attr">publisher-confirm-type:</span> <span class="string">simple</span>  <span class="comment"># 开启消息确认模式</span></span><br><span class="line">    <span class="attr">publisher-returns:</span> <span class="literal">true</span>    <span class="comment"># 使用return监听机制</span></span><br></pre></td></tr></table></figure><p>创建 confirm 和 return 监听</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MsgConfirmAndReturn</span> <span class="keyword">implements</span> <span class="title class_">RabbitTemplate</span>.ConfirmCallback, RabbitTemplate.ReturnCallback &#123;</span><br><span class="line"></span><br><span class="line">    <span class="type">Logger</span> <span class="variable">logger</span> <span class="operator">=</span> LoggerFactory.getLogger(MsgConfirmAndReturn.class);</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> RabbitTemplate rabbitTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@PostConstruct</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">init</span><span class="params">()</span> &#123;</span><br><span class="line">        rabbitTemplate.setConfirmCallback(<span class="built_in">this</span>);</span><br><span class="line">        rabbitTemplate.setReturnCallback(<span class="built_in">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">confirm</span><span class="params">(CorrelationData correlationData, <span class="type">boolean</span> b, String s)</span> &#123;</span><br><span class="line">        <span class="comment">// 此方法用于监听消息确认结果（消息是否发送到交换机）</span></span><br><span class="line">        <span class="keyword">if</span> (b) &#123;</span><br><span class="line">            logger.info(<span class="string">&quot;-------消息成功发送到交换机&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            logger.warn(<span class="string">&quot;-------消息发送到交换机失败&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">returnedMessage</span><span class="params">(Message message, <span class="type">int</span> i, String s, String s1, String s2)</span> &#123;</span><br><span class="line">        <span class="comment">//此方法用于return监听(当交换机分发消息到队列失败时执行)</span></span><br><span class="line">        logger.warn(<span class="string">&quot;~~~~~~~交换机分发消息到队列失败&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="RabbitMQ-的集群部署"><a href="#RabbitMQ-的集群部署" class="headerlink" title="RabbitMQ 的集群部署"></a>RabbitMQ 的集群部署</h3><ul><li>暂略</li></ul><h2 id="延迟机制"><a href="#延迟机制" class="headerlink" title="延迟机制"></a>延迟机制</h2><p><strong>延迟队列</strong></p><ul><li><p>延迟队列——消息进入到队列之后，延迟指定的时间才能被消费者消费</p></li><li><p><strong>AMQP 协议和 RabbitMQ 队列本身是不支持延迟队列功能的，但是可以通过 TTL（Time To Live）特性模拟延迟队列的功能</strong></p></li><li><p>TTL就是消息的存活时间。RabbitMQ 可以分别对队列和消息设置存活时间</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/530a/image-20200526162923111.webp" alt="img"></p><ul><li>在创建队列的时候可以设置队列的存活时间，当消息进入到队列并且在存活时间内没有消费者消费，则此消息就会从当前队列被移除；</li></ul></li><li><p>创建消息队列没有设置 TTL，但是消息设置了 TTL，那么当消息的存活时间结束，也会被移除；</p><ul><li>当 TTL 结束之后，我们可以指定将当前队列的消息转存到其他指定的队列</li></ul></li></ul><h3 id="使用延迟队列实现订单支付监控"><a href="#使用延迟队列实现订单支付监控" class="headerlink" title="使用延迟队列实现订单支付监控"></a>使用延迟队列实现订单支付监控</h3><ul><li><p>实现流程图</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/530a/image-20200526164139017.webp" alt="img"></p></li></ul><h4 id="创建交换机和队列"><a href="#创建交换机和队列" class="headerlink" title="创建交换机和队列"></a>创建交换机和队列</h4><div class="tabs" id="test4"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="test4-1">1.创建路由交换机</button><button type="button" class="tab " data-href="test4-2">2.创建消息队列</button><button type="button" class="tab " data-href="test4-3">3.创建死信队列</button><button type="button" class="tab " data-href="test4-4">4.队列绑定</button></ul><div class="tab-contents"><div class="tab-item-content active" id="test4-1"><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/530a/image-20200526164349455.webp" alt="img"></p></div><div class="tab-item-content" id="test4-2"><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/530a/image-20200526164546698.webp" alt="img"></p></div><div class="tab-item-content" id="test4-3"><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/530a/c13a91c80e0ad.webp" alt="img"></p></div><div class="tab-item-content" id="test4-4"><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/530a/image-20200526165116155.webp" alt="img"></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div>]]></content>
    
    
    <summary type="html">RabbitMQ 是消息队列，发送和接收的都是字符串/字节数组类型的消息,使用序列化对象,要求：1.传递的对象实现序列化接口 2.传递的对象的包名、类名、属性名必须一致</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="RabbitMQ" scheme="https://blog.imzjw.cn/tags/RabbitMQ/"/>
    
  </entry>
  
  <entry>
    <title>RabbitMQ（一）</title>
    <link href="https://blog.imzjw.cn/posts/50032/"/>
    <id>https://blog.imzjw.cn/posts/50032/</id>
    <published>2020-06-10T09:30:29.000Z</published>
    <updated>2020-06-10T09:30:29.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="RabbitMQ-用户管理"><a href="#RabbitMQ-用户管理" class="headerlink" title="RabbitMQ 用户管理"></a>RabbitMQ 用户管理</h2><h3 id="逻辑结构"><a href="#逻辑结构" class="headerlink" title="逻辑结构"></a>逻辑结构</h3><ul><li>用户</li><li>虚拟主机</li><li>队列</li></ul><h3 id="用户管理"><a href="#用户管理" class="headerlink" title="用户管理"></a>用户管理</h3><h4 id="命令行用户管理"><a href="#命令行用户管理" class="headerlink" title="命令行用户管理"></a>命令行用户管理</h4><ul><li><p>在 linux 中使用命令行创建用户</p><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 进入到rabbit_mq的sbin目录</span></span><br><span class="line"><span class="attr">cd</span> <span class="string">/usr/local/rabbitmq_server-3.7.0/sbin</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># 新增用户</span></span><br><span class="line"><span class="attr">./rabbitmqctl</span> <span class="string">add_user garvey admin123</span></span><br></pre></td></tr></table></figure></li><li><p>设置用户级别</p><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 用户级别：</span></span><br><span class="line"><span class="comment"># 1.administrator 可以登录控制台、查看所有信息、可以对RabbitMQ进行管理</span></span><br><span class="line"><span class="comment"># 2.monitoring 监控者 登录控制台、查看所有信息</span></span><br><span class="line"><span class="comment"># 3.policymaker 策略制定者 登录控制台、指定策略</span></span><br><span class="line"><span class="comment"># 4.managment 普通管理员 登录控制台</span></span><br><span class="line"></span><br><span class="line"><span class="attr">./rabbitmqctl</span> <span class="string">set_user_tags garvey administrator</span></span><br></pre></td></tr></table></figure></li></ul><h4 id="管理系统进行用户管理"><a href="#管理系统进行用户管理" class="headerlink" title="管理系统进行用户管理"></a>管理系统进行用户管理</h4><p>管理系统登录：访问 <code>http://你的主机ip:15672/</code></p><div class="tabs" id="test4"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="test4-1">1.新增用户</button><button type="button" class="tab " data-href="test4-2">2.创建虚拟主机</button><button type="button" class="tab " data-href="test4-3">3.删除用户</button><button type="button" class="tab " data-href="test4-4">4.用户绑定虚拟主机</button></ul><div class="tab-contents"><div class="tab-item-content active" id="test4-1"><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525101131727.webp" alt="img"></p></div><div class="tab-item-content" id="test4-2"><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525101434491.webp" alt="img"></p></div><div class="tab-item-content" id="test4-3"><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525101614733.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525101735067.webp" alt="img2"></p></div><div class="tab-item-content" id="test4-4"><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525102033725.webp" alt="img"></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="RabbitMQ-工作模式"><a href="#RabbitMQ-工作模式" class="headerlink" title="RabbitMQ 工作模式"></a>RabbitMQ 工作模式</h2><div class="note primary Disable flat"><p>RabbitMQ 提供了多种消息的通信方式 <a class="btn-beautify outline blue" href="https://www.rabbitmq.com/getstarted.html"   title="官方文档"><i class="far fa-hand-point-right"></i><span>官方文档</span></a></p></div><p>消息通信是由两个角色完成：<mark>消息生产者</mark>（producer）和 <mark>消息消费者</mark>（Consumer）</p><div class="tabs" id="test4"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="test4-1">简单模式</button><button type="button" class="tab " data-href="test4-2">工作模式</button><button type="button" class="tab " data-href="test4-3">订阅模式</button><button type="button" class="tab " data-href="test4-4">路由模式</button></ul><div class="tab-contents"><div class="tab-item-content active" id="test4-1"><div class="note success flat"><p>一个队列只有一个消费者</p></div><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525105401706.webp" alt="img"></p><p>生产者将消息发送到队列，消费者从队列取出数据</p></div><div class="tab-item-content" id="test4-2"><div class="note success flat"><p>多个消费者监听同一个队列</p></div><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525112959663.webp" alt="img"></p><p>多个消费者监听同一个队列，但多个消费者中只有一个消费者会成功的消费消息</p></div><div class="tab-item-content" id="test4-3"><div class="note success flat"><p>一个交换机绑定多个消息队列，每个消息队列有一个消费者监听</p></div><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525112005211.webp" alt="img"></p><p>消息生产者发送的消息可以被每一个消费者接收</p></div><div class="tab-item-content" id="test4-4"><div class="note success flat"><p>一个交换机绑定多个消息队列，每个消息队列都由自己唯一的 key，每个消息队列有一个消费者监听</p></div><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525112906683.webp" alt="img"></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="RabbitMQ交换机和队列管理"><a href="#RabbitMQ交换机和队列管理" class="headerlink" title="RabbitMQ交换机和队列管理"></a>RabbitMQ交换机和队列管理</h2><div class="tabs" id="test4"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="test4-1">创建队列</button><button type="button" class="tab " data-href="test4-2">创建交换机</button><button type="button" class="tab " data-href="test4-3">交换机绑定队列</button></ul><div class="tab-contents"><div class="tab-item-content active" id="test4-1"><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525114304743.webp" alt="img"></p></div><div class="tab-item-content" id="test4-2"><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525114934292.webp" alt="img"></p></div><div class="tab-item-content" id="test4-3"><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525115309962.webp" alt="img"></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525115721333.webp" alt="img"></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="在-Maven-中使用-MQ"><a href="#在-Maven-中使用-MQ" class="headerlink" title="在 Maven 中使用 MQ"></a>在 Maven 中使用 MQ</h2><p>RabbitMQ 队列结构</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525162927447.webp" alt="img"></p><div class="tabs" id="test3"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="test3-1">简单模式</button><button type="button" class="tab " data-href="test3-2">工作模式</button><button type="button" class="tab " data-href="test3-3">订阅模式</button><button type="button" class="tab " data-href="test3-4">路由模式</button></ul><div class="tab-contents"><div class="tab-item-content active" id="test3-1"><p><strong>消息生产者</strong></p><ul><li><p>创建 Maven 项目</p></li><li><p>添加 RabbitMQ 连接所需要的依赖 （<code>pom.xml</code>）</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.rabbitmq<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>amqp-client<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.10.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.slf4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>slf4j-log4j12<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.7.25<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.commons<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>commons-lang3<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.9<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>在 resources 目录下创建 <code>log4j.properties</code></p><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">log4j.rootLogger</span>=<span class="string">DEBUG,A1 log4j.logger.com.taotao = DEBUG </span></span><br><span class="line"><span class="attr">log4j.logger.org.mybatis</span> = <span class="string">DEBUG</span></span><br><span class="line"><span class="attr">log4j.appender.A1</span>=<span class="string">org.apache.log4j.ConsoleAppender</span></span><br><span class="line"><span class="attr">log4j.appender.A1.layout</span>=<span class="string">org.apache.log4j.PatternLayout</span></span><br><span class="line"><span class="attr">log4j.appender.A1.layout.ConversionPattern</span>=<span class="string">%-d&#123;yyyy-MM-dd HH:mm:ss,SSS&#125; [%t] [%c]-[%p] %m%n</span></span><br></pre></td></tr></table></figure></li><li><p>创建 MQ 连接帮助类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> GarveyZhong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2020/6/7 21:17</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConnectionUtil</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取连接</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IOException</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> TimeoutException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> Connection <span class="title function_">getConnection</span><span class="params">()</span> <span class="keyword">throws</span> IOException, TimeoutException &#123;</span><br><span class="line">        <span class="comment">// 1.创建连接工厂</span></span><br><span class="line">        <span class="type">ConnectionFactory</span> <span class="variable">factory</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ConnectionFactory</span>();</span><br><span class="line">        <span class="comment">// 2.在工厂对象中设置MQ的连接信息（ip，port，virtualhost，username，password）</span></span><br><span class="line">        factory.setHost(<span class="string">&quot;修改成你的服务器ip&quot;</span>);</span><br><span class="line">        factory.setPort(<span class="number">5672</span>);</span><br><span class="line">        factory.setVirtualHost(<span class="string">&quot;host1&quot;</span>);</span><br><span class="line">        factory.setUsername(<span class="string">&quot;garvey&quot;</span>);</span><br><span class="line">        factory.setPassword(<span class="string">&quot;admin&quot;</span>);</span><br><span class="line">        <span class="comment">// 3.通过工厂对象获取与MQ的连接</span></span><br><span class="line">        <span class="keyword">return</span> factory.newConnection();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 测试连接</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> args</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IOException</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> TimeoutException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException, TimeoutException &#123;</span><br><span class="line">        System.out.println(getConnection());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>消息生产者发送消息</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.zjw.mq.service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.rabbitmq.client.Channel;</span><br><span class="line"><span class="keyword">import</span> com.rabbitmq.client.Connection;</span><br><span class="line"><span class="keyword">import</span> com.zjw.mq.utils.ConnectionUtil;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SendMsg</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">msg</span> <span class="operator">=</span> <span class="string">&quot;Hello Garvey!&quot;</span>;</span><br><span class="line">        <span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> ConnectionUtil.getConnection();</span><br><span class="line">        <span class="type">Channel</span> <span class="variable">channel</span> <span class="operator">=</span> connection.createChannel();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 定义队列(使用Java代码在MQ中新建一个队列)</span></span><br><span class="line">        <span class="comment">// 参数1：定义的队列名称</span></span><br><span class="line">        <span class="comment">// 参数2：队列中的数据是否持久化（如果选择了持久化）</span></span><br><span class="line">        <span class="comment">// 参数3: 是否排外（当前队列是否为当前连接私有）</span></span><br><span class="line">        <span class="comment">// 参数4：自动删除（当此队列的连接数为0时，此队列会销毁（无论队列中是否还有数据））</span></span><br><span class="line">        <span class="comment">// 参数5：设置当前队列的参数</span></span><br><span class="line">        <span class="comment">// channel.queueDeclare(&quot;queue7&quot;,false,false,false,null);</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 参数1：交换机名称，如果直接发送信息到队列，则交换机名称为&quot;&quot;</span></span><br><span class="line">        <span class="comment">// 参数2：目标队列名称</span></span><br><span class="line">        <span class="comment">// 参数3：设置当前这条消息的属性（设置过期时间 10）</span></span><br><span class="line">        <span class="comment">// 参数4：消息的内容</span></span><br><span class="line">        channel.basicPublish(<span class="string">&quot;&quot;</span>, <span class="string">&quot;queue7&quot;</span>, <span class="literal">null</span>, msg.getBytes());</span><br><span class="line">        System.out.println(<span class="string">&quot;发送：&quot;</span> + msg);</span><br><span class="line"></span><br><span class="line">        channel.close();</span><br><span class="line">        connection.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul><hr><p><strong>消息消费者</strong></p><ul><li><p>创建 Maven 项目</p></li><li><p>添加依赖</p></li><li><p><code>log4j.properties</code></p></li><li><p><code>ConnetionUtil.java</code></p></li><li><p>消费者消费消息</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.zjw.mq.service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.rabbitmq.client.*;</span><br><span class="line"><span class="keyword">import</span> com.zjw.mq.utils.ConnectionUtil;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReceiceMsg</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> ConnectionUtil.getConnection();</span><br><span class="line">        <span class="type">Channel</span> <span class="variable">channel</span> <span class="operator">=</span> connection.createChannel();</span><br><span class="line">        <span class="type">Consumer</span> <span class="variable">consumer</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DefaultConsumer</span>(channel) &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handleDelivery</span><span class="params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="type">byte</span>[] body)</span> &#123;</span><br><span class="line">                <span class="comment">// body就是从队列中获取的数据</span></span><br><span class="line">                System.out.println(<span class="keyword">new</span> <span class="title class_">String</span>(body));</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        channel.basicConsume(<span class="string">&quot;queue7&quot;</span>, <span class="literal">true</span>, consumer);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul></div><div class="tab-item-content" id="test3-2"><div class="note success flat"><p>一个发送者多个消费者</p></div><p><strong>发送者</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SendMsg</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;请输入消息：&quot;</span>);</span><br><span class="line">        <span class="type">Scanner</span> <span class="variable">scanner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Scanner</span>(System.in);</span><br><span class="line">        <span class="type">String</span> <span class="variable">msg</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">while</span> (!<span class="string">&quot;quit&quot;</span>.equals(msg = scanner.nextLine())) &#123;</span><br><span class="line">            <span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> ConnectionUtil.getConnection();</span><br><span class="line">            <span class="type">Channel</span> <span class="variable">channel</span> <span class="operator">=</span> connection.createChannel();</span><br><span class="line"></span><br><span class="line">            channel.basicPublish(<span class="string">&quot;&quot;</span>, <span class="string">&quot;queue2&quot;</span>, <span class="literal">null</span>, msg.getBytes());</span><br><span class="line">            System.out.println(<span class="string">&quot;发送成功：&quot;</span> + msg);</span><br><span class="line"></span><br><span class="line">            channel.close();</span><br><span class="line">            connection.close();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>消费者一</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">    <span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> ConnectionUtil.getConnection();</span><br><span class="line">    <span class="type">Channel</span> <span class="variable">channel</span> <span class="operator">=</span> connection.createChannel();</span><br><span class="line"></span><br><span class="line">    <span class="type">Consumer</span> <span class="variable">consumer</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DefaultConsumer</span>(channel) &#123;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handleDelivery</span><span class="params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="type">byte</span>[] body)</span> &#123;</span><br><span class="line">            <span class="comment">// body就是从队列中获取的数据</span></span><br><span class="line">            <span class="type">String</span> <span class="variable">msg</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(body);</span><br><span class="line">            System.out.println(<span class="string">&quot;Consumer1接收：&quot;</span> + msg);</span><br><span class="line">            <span class="keyword">if</span> (<span class="string">&quot;wait&quot;</span>.equals(msg)) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    Thread.sleep(<span class="number">10000</span>);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    channel.basicConsume(<span class="string">&quot;queue2&quot;</span>, <span class="literal">true</span>, consumer);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>消费者二</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReceiceMsg2</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException, TimeoutException &#123;</span><br><span class="line">        <span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> ConnectionUtil.getConnection();</span><br><span class="line">        <span class="type">Channel</span> <span class="variable">channel</span> <span class="operator">=</span> connection.createChannel();</span><br><span class="line">        <span class="type">Consumer</span> <span class="variable">consumer</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DefaultConsumer</span>(channel) &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handleDelivery</span><span class="params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="type">byte</span>[] body)</span> &#123;</span><br><span class="line">                <span class="comment">// body就是从队列中获取的数据</span></span><br><span class="line">                System.out.println(<span class="string">&quot;Consumer2接收：&quot;</span> + <span class="keyword">new</span> <span class="title class_">String</span>(body));</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        channel.basicConsume(<span class="string">&quot;queue2&quot;</span>, <span class="literal">true</span>, consumer);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="test3-3"><div class="note success flat"><p>发送者  发送消息到交换机</p></div><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SendMsg</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;请输入消息：&quot;</span>);</span><br><span class="line">        <span class="type">Scanner</span> <span class="variable">scanner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Scanner</span>(System.in);</span><br><span class="line">        <span class="type">String</span> <span class="variable">msg</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">while</span> (!<span class="string">&quot;quit&quot;</span>.equals(msg = scanner.nextLine())) &#123;</span><br><span class="line">            <span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> ConnectionUtil.getConnection();</span><br><span class="line">            <span class="type">Channel</span> <span class="variable">channel</span> <span class="operator">=</span> connection.createChannel();</span><br><span class="line"></span><br><span class="line">            channel.basicPublish(<span class="string">&quot;ex1&quot;</span>, <span class="string">&quot;&quot;</span>, <span class="literal">null</span>, msg.getBytes());</span><br><span class="line">            System.out.println(<span class="string">&quot;发送：&quot;</span> + msg);</span><br><span class="line"></span><br><span class="line">            channel.close();</span><br><span class="line">            connection.close();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>消费者一</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReceiceMsg1</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> ConnectionUtil.getConnection();</span><br><span class="line">        <span class="type">Channel</span> <span class="variable">channel</span> <span class="operator">=</span> connection.createChannel();</span><br><span class="line"></span><br><span class="line">        <span class="type">Consumer</span> <span class="variable">consumer</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DefaultConsumer</span>(channel) &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handleDelivery</span><span class="params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="type">byte</span>[] body)</span> &#123;</span><br><span class="line">                <span class="comment">// body就是从队列中获取的数据</span></span><br><span class="line">                <span class="type">String</span> <span class="variable">msg</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(body);</span><br><span class="line">                System.out.println(<span class="string">&quot;Consumer1接收：&quot;</span> + msg);</span><br><span class="line">                <span class="keyword">if</span> (<span class="string">&quot;wait&quot;</span>.equals(msg)) &#123;</span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line">                        Thread.sleep(<span class="number">10000</span>);</span><br><span class="line">                    &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                        e.printStackTrace();</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        channel.basicConsume(<span class="string">&quot;queue3&quot;</span>, <span class="literal">true</span>, consumer);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>消费者二</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReceiceMsg2</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> ConnectionUtil.getConnection();</span><br><span class="line">        <span class="type">Channel</span> <span class="variable">channel</span> <span class="operator">=</span> connection.createChannel();</span><br><span class="line">        <span class="type">Consumer</span> <span class="variable">consumer</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DefaultConsumer</span>(channel) &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handleDelivery</span><span class="params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="type">byte</span>[] body)</span> &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;consumer2 == 收到了消息 == &quot;</span> + <span class="keyword">new</span> <span class="title class_">String</span>(body));</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        channel.basicConsume(<span class="string">&quot;queue4&quot;</span>, <span class="literal">true</span>, consumer);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="test3-4"><div class="note success flat"><p>发送者：发送消息到交换机</p></div><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SendMsg</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException, TimeoutException &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;请输入消息：&quot;</span>);</span><br><span class="line">        <span class="type">Scanner</span> <span class="variable">input</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Scanner</span>(System.in);</span><br><span class="line">        <span class="type">String</span> <span class="variable">msg</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">while</span> (!<span class="string">&quot;quit&quot;</span>.equals(msg = input.nextLine())) &#123;</span><br><span class="line">            <span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> ConnectionUtil.getConnection();</span><br><span class="line">            <span class="type">Channel</span> <span class="variable">channel</span> <span class="operator">=</span> connection.createChannel();</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (msg.startsWith(<span class="string">&quot;a&quot;</span>)) &#123;</span><br><span class="line">                channel.basicPublish(<span class="string">&quot;ex2&quot;</span>, <span class="string">&quot;a&quot;</span>, <span class="literal">null</span>, msg.getBytes());</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (msg.startsWith(<span class="string">&quot;b&quot;</span>)) &#123;</span><br><span class="line">                channel.basicPublish(<span class="string">&quot;ex2&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="literal">null</span>, msg.getBytes());</span><br><span class="line">            &#125;</span><br><span class="line">            System.out.println(<span class="string">&quot;发送成功：&quot;</span> + msg);</span><br><span class="line">            channel.close();</span><br><span class="line">            connection.close();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>消费者一</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReceiveMsg1</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> ConnectionUtil.getConnection();</span><br><span class="line">        <span class="type">Channel</span> <span class="variable">channel</span> <span class="operator">=</span> connection.createChannel();</span><br><span class="line"></span><br><span class="line">        <span class="type">Consumer</span> <span class="variable">consumer</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DefaultConsumer</span>(channel) &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handleDelivery</span><span class="params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="type">byte</span>[] body)</span> &#123;</span><br><span class="line">                <span class="comment">// body就是从队列中获取的数据</span></span><br><span class="line">                <span class="type">String</span> <span class="variable">msg</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(body);</span><br><span class="line">                System.out.println(<span class="string">&quot;Consumer1接收：&quot;</span> + msg);</span><br><span class="line">                <span class="keyword">if</span> (<span class="string">&quot;wait&quot;</span>.equals(msg)) &#123;</span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line">                        Thread.sleep(<span class="number">10000</span>);</span><br><span class="line">                    &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                        e.printStackTrace();</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        channel.basicConsume(<span class="string">&quot;queue5&quot;</span>, <span class="literal">true</span>, consumer);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>消费者二</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReceiceMsg2</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> ConnectionUtil.getConnection();</span><br><span class="line">        <span class="type">Channel</span> <span class="variable">channel</span> <span class="operator">=</span> connection.createChannel();</span><br><span class="line">        <span class="type">Consumer</span> <span class="variable">consumer</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DefaultConsumer</span>(channel) &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handleDelivery</span><span class="params">(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, <span class="type">byte</span>[] body)</span> &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;Consumer2接收：&quot;</span> + <span class="keyword">new</span> <span class="title class_">String</span>(body));</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        channel.basicConsume(<span class="string">&quot;queue6&quot;</span>, <span class="literal">true</span>, consumer);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="Spring-Boot-中使用-MQ"><a href="#Spring-Boot-中使用-MQ" class="headerlink" title="Spring Boot 中使用 MQ"></a>Spring Boot 中使用 MQ</h2><div class="note warning flat"><p>Spring Boot 应用可以完成自动配置及依赖注入— —可以通过 <code>Spring</code> 直接提供与 MQ 的连接对象</p></div><div class="tabs" id="test4"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="test4-1">消息生产者</button><button type="button" class="tab " data-href="test4-2">消息消费者</button></ul><div class="tab-contents"><div class="tab-item-content active" id="test4-1"><p>创建 Spring Boot 应用，添加依赖</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/50032/image-20200525163617224.webp" alt="img"></p><p>配置 application.yml</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">rabbitmq:</span></span><br><span class="line">    <span class="attr">host:</span> <span class="string">你的主机ip</span></span><br><span class="line">    <span class="attr">virtual-host:</span> <span class="string">host1</span></span><br><span class="line">    <span class="attr">port:</span> <span class="number">5672</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">garvey</span></span><br><span class="line">    <span class="attr">password:</span> <span class="string">admin123</span></span><br></pre></td></tr></table></figure><p>发送消息</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> AmqpTemplate amqpTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sendMsg</span><span class="params">(String msg)</span> &#123;</span><br><span class="line">        <span class="comment">// 1. 发送消息到队列</span></span><br><span class="line">        amqpTemplate.convertAndSend(<span class="string">&quot;queue1&quot;</span>, msg);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 2. 发送消息到交换机(订阅交换机)</span></span><br><span class="line">        amqpTemplate.convertAndSend(<span class="string">&quot;ex1&quot;</span>, <span class="string">&quot;&quot;</span>, msg);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 3. 发送消息到交换机(路由交换机)</span></span><br><span class="line">        amqpTemplate.convertAndSend(<span class="string">&quot;ex2&quot;</span>, <span class="string">&quot;a&quot;</span>, msg);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="test4-2"><ol><li><p>创建项目添加依赖</p></li><li><p>配置yml</p></li><li><p>接收消息</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="comment">// @RabbitListener(queues = &#123;&quot;queue1&quot;,&quot;queue2&quot;&#125;)</span></span><br><span class="line"><span class="meta">@RabbitListener(queues = &quot;queue1&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReceiveMsgService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RabbitHandler</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receiveMsg</span><span class="params">(String msg)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;接收MSG：&quot;</span> + msg);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//@RabbitHandler</span></span><br><span class="line">    <span class="comment">//public void receiveMsg(byte[] bs)&#123;</span></span><br><span class="line">    <span class="comment">//</span></span><br><span class="line">    <span class="comment">//&#125;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ol></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div>]]></content>
    
    
    <summary type="html">RabbitMQ 用户管理，逻辑结构：用户、虚拟主机、队列，用户管理，在 linux 中使用命令行创建用户，设置用户级别，管理系统登录...</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="RabbitMQ" scheme="https://blog.imzjw.cn/tags/RabbitMQ/"/>
    
  </entry>
  
  <entry>
    <title>Redis常用配置</title>
    <link href="https://blog.imzjw.cn/posts/10187/"/>
    <id>https://blog.imzjw.cn/posts/10187/</id>
    <published>2020-06-01T12:39:26.000Z</published>
    <updated>2020-06-01T12:39:26.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="INCLUDES-包含"><a href="#INCLUDES-包含" class="headerlink" title="INCLUDES (包含)"></a>INCLUDES (包含)</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">include /path/to/other.conf 这在你有标准配置模板但是每个 redis 服务器又需要个性设置的时候很有用</span><br></pre></td></tr></table></figure><h2 id="GENERAL-一般常用"><a href="#GENERAL-一般常用" class="headerlink" title="GENERAL (一般常用)"></a>GENERAL (一般常用)</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">daemonize yes # Redis 默认不是以守护进程的方式运行，可以通过该配置项修改，使用yes启用守护进程(yes：后台运行；no：不是后台运行)</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">protected-mode yes # 保护模式，默认开启。开启该参数后，redis只会本地进行访问，拒绝外部访问。</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pidfile /var/run/redis/redis-server.pid # redis的进程文件</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">port 6379 # redis监听的端口号</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tcp-backlog 511 #TCP连接队列的长度</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bind 127.0.0.1 # 指定redis只接收来自于该IP地址的请求，如果不进行设置，那么将处理所有请求</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">timeout 0 # 当客户端闲置多长时间后关闭连接，如果指定为0，表示关闭该功能</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定日志记录级别，Redis总共支持四个级别：debug、verbose、notice、warning，默认为verbose;</span></span><br><span class="line">loglevel notice</span><br><span class="line">debug # 很多信息，方便开发、测试</span><br><span class="line">verbose # 许多有用的信息，但是没有debug级别信息多</span><br><span class="line">notice # 适当的日志级别，适合生产环境</span><br><span class="line">warn # 只有非常重要的信息</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">logfile /var/log/redis/redis-server.log # 日志记录方式，默认为标准输出，如果配置Redis为守护进程方式运行，而这里又配置为日志记录方式为标准输出，则日志将会发送给/dev/null。空字符串的话，日志会打印到标准输出设备。后台运行的redis标准输出是/dev/null</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">databases 16 # 设置数据库的数量，默认数据库为0，可以使用SELECT &lt;dbid&gt;命令在连接上指定数据库id</span><br></pre></td></tr></table></figure><h2 id="SNAPSHOTTING-快照"><a href="#SNAPSHOTTING-快照" class="headerlink" title="SNAPSHOTTING (快照)"></a>SNAPSHOTTING (快照)</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">save &lt;seconds&gt; &lt;changes&gt; &lt;指定时间间隔&gt; &lt;执行指定次数更新操作&gt;，满足条件就将内存中的数据同步到硬盘中。</span></span><br><span class="line">save 900 1</span><br><span class="line">save 300 10</span><br><span class="line">save 60 10000</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">注释掉“save”这一行配置项就可以让保存数据库功能失效，设置sedis进行数据库镜像的频率。</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">900秒 15分钟内至少1个key值改变（则进行数据库保存--持久化）</span> </span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">300秒 5分钟内至少10个key值改变（则进行数据库保存--持久化）</span> </span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">60秒  1分钟内至少10000个key值改变（则进行数据库保存--持久化）</span></span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">stop-writes-on-bgsave-error yes # 当RDB持久化出现错误后，是否依然进行继续进行工作，yes：不能进行工作，no：可以继续进行工作，可以通过info中的rdb_last_bgsave_status了解RDB持久化是否有错误</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rdbcompression yes # 使用压缩rdb文件，rdb文件压缩使用LZF压缩算法，yes：压缩，但是需要一些cpu的消耗。no：不压缩，需要更多的磁盘空间</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rdbchecksum yes # 是否校验rdb文件。从rdb格式的第五个版本开始，在rdb文件的末尾会带上CRC64的校验和。这跟有利于文件的容错性，但是在保存rdb文件的时候，会有大概10%的性能损耗，所以如果你追求高性能，可以关闭该配置。</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dbfilename dump.rdb # rdb文件的名称</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dir /var/lib/redis # 数据目录，数据库的写入会在这个目录。rdb、aof文件也会写在这个目录</span><br></pre></td></tr></table></figure><h2 id="REPLICATION-复制"><a href="#REPLICATION-复制" class="headerlink" title="REPLICATION (复制)"></a>REPLICATION (复制)</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">slaveof &lt;masterip&gt; &lt;masterport&gt; 设置当本机为slav服务时，设置master服务的IP地址及端口，在Redis启动时，它会自动从master进行数据同步</span></span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">masterauth &lt;master-password&gt; 当master服务设置了密码保护时，slav服务连接master的密码</span></span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">slave-read-only yes # 作为从服务器，默认情况下是只读的（yes），可以修改成NO，用于写（不建议）。</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">slave-priority 100 # 当master不可用，Sentinel会根据slave的优先级选举一个master。最低的优先级的slave，当选master。而配置成0，永远不会被选举</span><br></pre></td></tr></table></figure><h2 id="SECURITY-安全"><a href="#SECURITY-安全" class="headerlink" title="SECURITY (安全)"></a>SECURITY (安全)</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">requirepass foobared requirepass 配置可以让用户使用AUTH命令来认证密码，才能使用其他命令。这让redis可以使用在不受信任的网络中。为了保持向后的兼容性，可以注释该命令，因为大部分用户也不需要认证。使用requirepass的时候需要注意，因为redis太快了，每秒可以认证15w次密码，简单的密码很容易被攻破，所以最好使用一个更复杂的密码。</span></span><br></pre></td></tr></table></figure><h2 id="LIMITS-限制"><a href="#LIMITS-限制" class="headerlink" title="LIMITS (限制)"></a>LIMITS (限制)</h2><ul><li><strong>maxclients 10000</strong> <ul><li>设置能连上redis的最大客户端连接数量。默认是10000个客户端连接。由于redis不区分连接是客户端连接还是内部打开文件或者和slave连接等，所以maxclients最小建议设置到32。如果超过了maxclients，redis会给新的连接发送’max number of clients reached’，并关闭连接。</li></ul></li><li><strong>maxmemory &lt;bytes&gt;</strong> <ul><li>redis配置的最大内存容量。当内存满了，需要配合maxmemory-policy策略进行处理。注意slave的输出缓冲区是不计算在maxmemory内的。所以为了防止主机内存使用完，建议设置的maxmemory需要更小一些。</li></ul></li><li><strong>maxmemory-policy noeviction</strong> 内存容量超过maxmemory后的处理策略<ul><li>volatile-lru（Least Recently Used 即最近最少使用）：利用LRU算法移除key，只对设置了过期时间的key。</li><li>allkeys-lru：利用LRU算法移除所有key，与是否设置过期时间没关系。</li><li>volatile-random：随机移除设置了过期时间的key。</li><li>allkeys-random：随机移除任何key。与是否设置过期时间没关系。</li><li>volatile-ttl：移除即将过期的key。</li><li>noeviction：不移除任何key，只是返回一个写错误。</li></ul></li></ul><h2 id="APPEND-ONLY-MODE-追加"><a href="#APPEND-ONLY-MODE-追加" class="headerlink" title="APPEND ONLY MODE (追加)"></a>APPEND ONLY MODE (追加)</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">appendonly no # 默认redis使用的是rdb方式持久化，这种方式在许多应用中已经足够用了。但是redis如果中途宕机，会导致可能有几分钟的数据丢失，根据save来策略进行持久化，Append Only File是另一种持久化方式，可以提供更好的持久化特性。Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件，每次启动时Redis都会先把这个文件的数据读入内存里，先忽略RDB文件。</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">appendfilename &quot;appendonly.aof&quot; # aof文件名</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">appendfsync everysec # aof持久化策略的配置。no表示不执行fsync，由操作系统保证数据同步到磁盘，速度最快。always表示每次写入都执行fsync，以保证数据同步到磁盘。everysec表示每秒执行一次fsync，可能会导致丢失这1s数据。</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">auto-aof-rewrite-percentage 100 # aof自动重写配置。当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写，即当aof文件增长到一定大小的时候Redis能够调用bgrewriteaof对日志文件进行重写。当前AOF文件大小是上次日志重写得到AOF文件大小的二倍（设置为100）时，自动启动新的日志重写过程。</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">auto-aof-rewrite-min-size 64mb # 设置允许重写的最小aof文件大小，避免了达到约定百分比但尺寸仍然很小的情况还要重写</span><br></pre></td></tr></table></figure><h2 id="redis-conf常见配置"><a href="#redis-conf常见配置" class="headerlink" title="redis.conf常见配置"></a>redis.conf常见配置</h2><p><strong>redis.conf</strong> 配置项说明如下：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Redis默认不是以守护进程的方式运行，可以通过该配置项修改，使用<span class="built_in">yes</span>启用守护进程</span></span><br><span class="line">daemonize no</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">当Redis以守护进程方式运行时，Redis默认会把pid写入/var/run/redis.pid文件，可以通过pidfile指定</span></span><br><span class="line">pidfile /var/run/redis.pid</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定Redis监听端口，默认端口为6379，作者在自己的一篇博文中解释了为什么选用6379作为默认端口，因为6379在手机按键上MERZ对应的号码，而MERZ取自意大利歌女Alessia Merz的名字</span></span><br><span class="line">port 6379</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">绑定的主机地址</span></span><br><span class="line">bind 127.0.0.1</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">当 客户端闲置多长时间后关闭连接，如果指定为0，表示关闭该功能</span></span><br><span class="line">timeout 300</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定日志记录级别，Redis总共支持四个级别：debug、verbose、notice、warning，默认为verbose</span></span><br><span class="line">loglevel verbose</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">日志记录方式，默认为标准输出，如果配置Redis为守护进程方式运行，而这里又配置为日志记录方式为标准输出，则日志将会发送给/dev/null</span></span><br><span class="line">logfile stdout</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置数据库的数量，默认数据库为0，可以使用SELECT &lt;dbid&gt;命令在连接上指定数据库<span class="built_in">id</span></span></span><br><span class="line">databases 16</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定在多长时间内，有多少次更新操作，就将数据同步到数据文件，可以多个条件配合</span></span><br><span class="line">save &lt;seconds&gt; &lt;changes&gt;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Redis默认配置文件中提供了三个条件：</span></span><br><span class="line">    #save 900 1 # 900秒（15分钟）内有1个更改</span><br><span class="line">    #save 300 10 # 300秒（5分钟）内有10个更改</span><br><span class="line">    #save 60 10000 # 60秒内有10000个更改</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定存储至本地数据库时是否压缩数据，默认为<span class="built_in">yes</span>，Redis采用LZF压缩，如果为了节省CPU时间，可以关闭该选项，但会导致数据库文件变的巨大</span></span><br><span class="line">rdbcompression yes</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定本地数据库文件名，默认值为dump.rdb</span></span><br><span class="line">dbfilename dump.rdb</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定本地数据库存放目录</span></span><br><span class="line">dir ./</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置当本机为slav服务时，设置master服务的IP地址及端口，在Redis启动时，它会自动从master进行数据同步</span></span><br><span class="line">slaveof &lt;masterip&gt; &lt;masterport&gt;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">当master服务设置了密码保护时，slav服务连接master的密码</span></span><br><span class="line">masterauth &lt;master-password&gt;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置Redis连接密码，如果配置了连接密码，客户端在连接Redis时需要通过AUTH &lt;password&gt;命令提供密码，默认关闭</span></span><br><span class="line">requirepass foobared</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置同一时间最大客户端连接数，默认无限制，Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数，如果设置 maxclients 0，表示不作限制。当客户端连接数到达限制时，Redis会关闭新的连接并向客户端返回max number of clients reached错误信息</span></span><br><span class="line">maxclients 128</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定Redis最大内存限制，Redis在启动时会把数据加载到内存中，达到最大内存后，Redis会先尝试清除已到期或即将到期的Key，当此方法处理 后，仍然到达最大内存设置，将无法再进行写入操作，但仍然可以进行读取操作。Redis新的vm机制，会把Key存放内存，Value会存放在swap区</span></span><br><span class="line">maxmemory &lt;bytes&gt;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定是否在每次更新操作后进行日志记录，Redis在默认情况下是异步的把数据写入磁盘，如果不开启，可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的，所以有的数据会在一段时间内只存在于内存中。默认为no</span></span><br><span class="line">appendonly no</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定更新日志文件名，默认为appendonly.aof</span></span><br><span class="line">appendfilename appendonly.aof</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定更新日志条件，共有3个可选值：</span> </span><br><span class="line">    #no：表示等操作系统进行数据缓存同步到磁盘（快） </span><br><span class="line">    #always：表示每次更新操作后手动调用fsync()将数据写到磁盘（慢，安全） </span><br><span class="line">    #everysec：表示每秒同步一次（折衷，默认值）</span><br><span class="line">    #appendfsync everysec</span><br><span class="line">    </span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定是否启用虚拟内存机制，默认值为no，简单的介绍一下，VM机制将数据分页存放，由Redis将访问量较少的页即冷数据swap到磁盘上，访问多的页面由磁盘自动换出到内存中（在后面的文章我会仔细分析Redis的VM机制）</span></span><br><span class="line">vm-enabled no</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">虚拟内存文件路径，默认值为/tmp/redis.swap，不可多个Redis实例共享</span></span><br><span class="line">vm-swap-file /tmp/redis.swap</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0</span></span><br><span class="line">vm-max-memory 0</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Redis swap文件分成了很多的page，一个对象可以保存在多个page上面，但一个page上不能被多个对象共享，vm-page-size是要根据存储的 数据大小来设定的，作者建议如果存储很多小对象，page大小最好设置为32或者64bytes；如果存储很大大对象，则可以使用更大的page，如果不 确定，就使用默认值</span></span><br><span class="line">vm-page-size 32</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置swap文件中的page数量，由于页表（一种表示页面空闲或使用的bitmap）是在放在内存中的，，在磁盘上每8个pages将消耗1byte的内存。</span></span><br><span class="line">vm-pages 134217728</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的，可能会造成比较长时间的延迟。默认值为4</span></span><br><span class="line">vm-max-threads 4</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">设置在向客户端应答时，是否把较小的包合并为一个包发送，默认为开启</span></span><br><span class="line">glueoutputbuf yes</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定在超过一定的数量或者最大的元素超过某一临界值时，采用一种特殊的哈希算法</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">hash-max-zipmap-entries 64</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">hash-max-zipmap-value 512</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定是否激活重置哈希，默认为开启（后面在介绍Redis的哈希算法时具体介绍）</span></span><br><span class="line">activerehashing yes</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">指定包含其它的配置文件，可以在同一主机上多个Redis实例之间使用同一份配置文件，而同时各个实例又拥有自己的特定配置文件</span></span><br><span class="line">include /path/to/local.conf</span><br></pre></td></tr></table></figure><p>配置信息可以通过<code>config get</code> 获取</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">config get port # 获取redis端口号</span><br><span class="line">config get dir # 获取启动路径</span><br><span class="line">config get requirepass # 获取密码</span><br><span class="line">config set requirepass &quot;123456&quot; # 设置redis密码</span><br></pre></td></tr></table></figure><h2 id="持久化-RDB-AOF"><a href="#持久化-RDB-AOF" class="headerlink" title="持久化(RDB/AOF)"></a>持久化(RDB/AOF)</h2><h3 id="RDB"><a href="#RDB" class="headerlink" title="RDB"></a>RDB</h3><p>RDB（Redis Database） 是 Redis 默认的持久化方案。<code>它可以在指定的时间间隔内将内存中的数据集快照写入磁盘</code>，<br>也就是行话讲的 Snapshot 快照，它恢复时是将快照文件直接读到内存里，在 RDB 方式下，你有两种选择：</p><ul><li><p>一种是手动执行持久化数据命令来让 redis 进行一次数据快照，</p></li><li><p>另一种则是根据你所配置的配置文件的策略，达到策略的某些条件时来自动持久化数据。</p></li></ul><p>而手动执行持久化命令，你依然有两种选择：</p><ul><li><p><strong>save</strong> 命令</p><p><code>save 命令执行时只管保存，其他不管，全部阻塞</code>，save 操作在 Redis 主线程中工作，因此会<strong>阻塞</strong>其他请求操作，应该避免使用。（默认下，持久化到<strong>dump.rdb</strong> 文件，并且在 redis 重启后，自动读取其中文件，据悉，通常情况下<strong>一千万</strong>的字符串类型键，<strong>1GB</strong> 的快照文件，同步到内存中的 时间是 <strong>20-30秒</strong>）</p></li><li><p><strong>bgsave</strong> 命令。</p><p><code>bgsave 后台备份，在备份的同时可以处理输入的数据</code>，bgSave 则是调用 Fork,产生子进程，父进程继续处理请求。子进程将数据写入临时文件，并在写完后，替换原有的 <code>.rdb</code> 文件。Fork 发生时，父子进程内存共享，所以为了不影响子进程做数据快照，在这期间修改的数据，将会被复制一份，而不进共享内存。所以说，RDB 所持久化的数据，是 Fork 发生时的数据。在这样的条件下进行持久化数据，如果因为某些情况宕机，则会丢失一段时间的数据。如果你的实际情况对数据丢失没那么敏感，丢失的也可以从传统数据库中获取或者说丢失部分也无所谓，那么你可以选择 RDB 持久化方式。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash"><span class="comment">## 生产环境推荐配置（系统默认的）</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">15分钟修改1次</span></span><br><span class="line">save 900 1</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">5分钟修改10次</span></span><br><span class="line">save 300 10</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">一分钟修改一万次</span></span><br><span class="line">save 60 10000</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash"><span class="comment">## 如果想禁用</span></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">save <span class="string">&quot;&quot;</span></span></span><br></pre></td></tr></table></figure></li></ul><p>这是配置文件<strong>默认的策略</strong>，他们之间的关系是或，每隔 <strong>900</strong> 秒，在这期间变化了至少<strong>一个</strong>键值，做快照。或者每<strong>三百秒</strong>，变化了<strong>十个</strong>键值做快照。或者每<strong>六十</strong>秒，变化了至少<strong>一万</strong>个键值，做快照。  </p><h3 id="RDB配置"><a href="#RDB配置" class="headerlink" title="RDB配置"></a>RDB配置</h3><h4 id="触发RDB快照"><a href="#触发RDB快照" class="headerlink" title="触发RDB快照"></a>触发RDB快照</h4><ul><li>在指定的时间间隔内，执行指定次数的写操作。</li><li>执行save（阻塞， 只管保存快照，其他的等待） 或者是bgsave （异步）命令。</li><li>执行flushall 命令，清空数据库所有数据，意义不大。</li><li>执行shutdown 命令，保证服务器正常关闭且不丢失任何数据，意义也不大。 </li></ul><h4 id="数据恢复"><a href="#数据恢复" class="headerlink" title="数据恢复"></a>数据恢复</h4><p>将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可。</p><h4 id="优势"><a href="#优势" class="headerlink" title="优势"></a>优势</h4><ul><li>适合大规模的数据恢复</li><li>对数据完整性要求不高</li></ul><h4 id="劣势"><a href="#劣势" class="headerlink" title="劣势"></a>劣势</h4><ul><li>在一定时间做一次备份，如果redis意外宕机的话就会丢失最后一次快照后的所有数据</li><li>Fork的时候，内存中的数据被克隆了一份，在fork的过程是非常耗时的，可能会导致Redis在一些毫秒级内不能响应客户端的请求</li></ul><h3 id="AOF"><a href="#AOF" class="headerlink" title="AOF"></a>AOF</h3><ul><li>AOF（Append Only File） ，Redis 默认不开启。它的出现是为了弥补RDB的不足（数据的不一致性），所以<strong>它采用日志的形式来记录每个写操作</strong>，并<strong>追加</strong>到文件中。Redis 重启的会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。</li><li>配置文件中的appendonly修改为yes。开启AOF持久化后，你所执行的每一条指令，都会被记录到<strong>appendonly.aof</strong>文件中。但事实上，并不会立即将命令写入到硬盘文件中，而是写入到硬盘缓存，在接下来的策略中，配置多久来从硬盘缓存写入到硬盘文件。所以在一定程度一定条件下，还是会有数据丢失，不过你可以大大减少数据损失。</li><li>这里是配置AOF持久化的策略。redis默认使用<strong>everysec</strong>，就是说每秒持久化一次，而always则是每次操作都会立即写入aof文件中。而<strong>no</strong>则是不主动进行同步操作，是默认30s一次。当然<strong>always</strong>一定是效率最低的，个人认为<strong>everysec</strong>就够用了，数据安全性能又高</li></ul><h4 id="AOF配置"><a href="#AOF配置" class="headerlink" title="AOF配置"></a>AOF配置</h4><ul><li>开启AOF配置</li></ul><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># AOF and RDB persistence can be enabled at the same time without problems.</span></span><br><span class="line"><span class="comment"># AOF和RDB的持久化是可以同时开启的</span></span><br><span class="line"><span class="comment"># If the AOF is enabled on startup Redis will load the AOF, that is the file</span></span><br><span class="line"><span class="comment"># 如果启动时启用了AOF, Redis将先加载AOF</span></span><br><span class="line"><span class="comment"># with the better durability guarantees.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># 开启aop配置</span></span><br><span class="line"><span class="attr">appendonly</span> <span class="string">yes</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># aop生成文件名称</span></span><br><span class="line"><span class="attr">appendfilename</span> <span class="string">&quot;appendonly.aof&quot;</span></span><br></pre></td></tr></table></figure><h4 id="数据恢复-1"><a href="#数据恢复-1" class="headerlink" title="数据恢复"></a>数据恢复</h4><p>将备份文件 (appendonly.aof) 移动到 redis 安装目录并启动服务即可。</p><h4 id="触发AOF快照"><a href="#触发AOF快照" class="headerlink" title="触发AOF快照"></a>触发AOF快照</h4><p>根据配置文件触发，可以是每次执行触发，可以是每秒触发，可以不同步。</p><ul><li>always：每修改同步</li><li><code>everysec</code>：每秒同步</li><li>no：不同步</li></ul><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 每修改同步：同步持久化 每次发生数据变更会被立即记录到磁盘，性能较差但数据完整性比较好</span></span><br><span class="line"><span class="attr">appendfsync</span> <span class="string">always</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># 每秒同步：默认设置，异步操作，每秒记录   如果一秒内宕机，有数据丢失（推荐）</span></span><br><span class="line"><span class="attr">appendfsync</span> <span class="string">everysec</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># 不同步：从不同步</span></span><br><span class="line"><span class="attr">appendfsync</span> <span class="string">no</span></span><br></pre></td></tr></table></figure><h4 id="AOF-rewrite-重写"><a href="#AOF-rewrite-重写" class="headerlink" title="AOF rewrite(重写)"></a>AOF rewrite(重写)</h4><ul><li><p>AOF采用文件追加方式，文件会越来越大为避免出现此种情况，新增了重写机制，当AOF文件的大小超过所设定的阈值时，Redis就会启动AOF文件的内容压缩，只保留可以恢复数据的最小指令集.可以使用命令bgrewriteaof。</p></li><li><p>AOF文件持续增长而过大时，会fork出一条新进程来将文件重写(也是先写临时文件最后再rename)，<br>遍历新进程的内存中数据，每条记录有一条的Set语句。重写aof文件的操作，并没有读取旧的aof文件，<br>而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件，这点和快照有点类似。</p></li><li><p><code>Redis会记录上次重写时的AOF大小，默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。</code></p></li></ul><h4 id="AOP文件修复"><a href="#AOP文件修复" class="headerlink" title="AOP文件修复"></a>AOP文件修复</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-check-aof --fix appendonly.aof</span><br></pre></td></tr></table></figure><h4 id="RDB-amp-AOF比较"><a href="#RDB-amp-AOF比较" class="headerlink" title="RDB &amp; AOF比较"></a>RDB &amp; AOF比较</h4><h4 id="优势-1"><a href="#优势-1" class="headerlink" title="优势"></a>优势</h4><p>RDB：适合大规模的数据恢复。如果业务对数据完整性和一致性要求不高，RDB是很好的选择。</p><p>AOF：数据的完整性和一致性更高。</p><h4 id="劣势-1"><a href="#劣势-1" class="headerlink" title="劣势"></a>劣势</h4><p>RDB：数据的完整性和一致性不高，因为RDB可能在最后一次备份时宕机了。 备份时占用内存，因为Redis 在备份时会独立创建一个子进程，将数据写入到一个临时文件（此时内存中的数据是原来的两倍哦），最后再将临时文件替换之前的备份文件。所以Redis 的持久化和数据的恢复要选择在夜深人静的时候执行是比较合理的。</p><p>AOF：因为AOF记录的内容多，文件会越来越大，数据恢复也会越来越慢。</p><h4 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h4><ul><li>Redis 默认开启RDB持久化方式，在指定的时间间隔内，执行指定次数的写操作，则将内存中的数据写入到磁盘中。</li><li>RDB 持久化适合大规模的数据恢复但它的数据一致性和完整性较差。</li><li>Redis 需要手动开启AOF持久化方式，默认是每秒将写操作日志追加到AOF文件中。</li><li>AOF 的数据完整性比RDB高，但记录内容多了，会影响数据恢复的效率。</li><li>Redis 针对 AOF文件大的问题，提供重写的瘦身机制。</li><li>若只打算用Redis 做缓存，可以关闭持久化。</li><li>若打算使用Redis 的持久化。建议RDB和AOF都开启。其实RDB更适合做数据的备份，留一后手。AOF出问题了，还有RDB</li></ul><h3 id="事物"><a href="#事物" class="headerlink" title="事物"></a>事物</h3><p>redis的事务中，一次执行多条命令，本质是一组命令的集合，一个事务中所有的命令将被序列化，即按顺序执行而不会被其他命令插入在redis中，事务的作用就是在一个队列中一次性、顺序性、排他性的执行一系列的命令。事务可以一次执行多个命令， 并且带有以下两个重要的保证：</p><ol><li><p>事务是一个单独的隔离操作：事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中，不会被其他客户端发送来的命令请求所打断。</p></li><li><p>事务是一个原子操作：事务中的命令要么全部被执行，要么全部都不执行。</p></li></ol><h4 id="使用事物"><a href="#使用事物" class="headerlink" title="使用事物"></a>使用事物</h4><p>用multi命令开启事物，用exec执行事物。</p><p>例子：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379&gt; MULTI</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; set k1 v1</span><br><span class="line">QUEUED</span><br><span class="line">127.0.0.1:6379&gt; set k2 v2</span><br><span class="line">QUEUED</span><br><span class="line">127.0.0.1:6379&gt; get k1</span><br><span class="line">QUEUED</span><br><span class="line">127.0.0.1:6379&gt; set k3 v3</span><br><span class="line">QUEUED</span><br><span class="line">127.0.0.1:6379&gt; EXEC</span><br><span class="line">1) OK</span><br><span class="line">2) OK</span><br><span class="line">3) &quot;v1&quot;</span><br><span class="line">4) OK</span><br></pre></td></tr></table></figure><h4 id="执行结果："><a href="#执行结果：" class="headerlink" title="执行结果："></a>执行结果：</h4><ol><li>正常执行完成；</li><li>有命令入队不成功，事物执行失败，全部命令都不执行；</li><li>命令入队成功，事物照常执行，有命令执行失败，其余命令正常执行；</li></ol><h4 id="放弃事物"><a href="#放弃事物" class="headerlink" title="放弃事物"></a>放弃事物</h4><p>在使用multi开起事物之后，可以使用discard放弃当前事物。</p><p>例子：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379&gt; MULTI</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; set k1 vv</span><br><span class="line">QUEUED</span><br><span class="line">127.0.0.1:6379&gt; set k2 vv2</span><br><span class="line">QUEUED</span><br><span class="line">127.0.0.1:6379&gt; DISCARD</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; get k1</span><br><span class="line">&quot;v1&quot;</span><br></pre></td></tr></table></figure><h4 id="事物-监控"><a href="#事物-监控" class="headerlink" title="事物-监控"></a>事物-监控</h4><p>redis可以监控一个或多个键，一旦其中有一个键被修改（或删除），之后的事务就不会执行。监控一直持续到EXEC命令（事务中的命令是在EXEC之后才执行的）。</p><h4 id="监控"><a href="#监控" class="headerlink" title="监控"></a>监控</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">watch key [key ...]</span><br></pre></td></tr></table></figure><p>例子：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379&gt; watch k1</span><br><span class="line">127.0.0.1:6379&gt; MULTI</span><br><span class="line">OK</span><br><span class="line">127.0.0.1:6379&gt; set k1 v1</span><br><span class="line">QUEUED</span><br><span class="line">127.0.0.1:6379&gt; set k2 v2</span><br><span class="line">QUEUED</span><br><span class="line">127.0.0.1:6379&gt; EXEC</span><br><span class="line">(ni1)</span><br></pre></td></tr></table></figure><h4 id="放弃监控"><a href="#放弃监控" class="headerlink" title="放弃监控"></a>放弃监控</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">unwatch 取消 WATCH 命令对所有 key 的监视。</span><br></pre></td></tr></table></figure><h3 id="消息发布订阅"><a href="#消息发布订阅" class="headerlink" title="消息发布订阅"></a>消息发布订阅</h3><h4 id="消息发布订阅是什么"><a href="#消息发布订阅是什么" class="headerlink" title="消息发布订阅是什么"></a>消息发布订阅是什么</h4><ul><li><p>Redis 发布订阅(pub/sub)是一种消息通信模式：发送者(pub)发送消息，订阅者(sub)接收消息。</p></li><li><p>Redis 客户端可以订阅任意数量的频道。</p></li><li><p>下图展示了频道 channel1 ， 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/10187/20200601220920.webp" alt="img"></p></li><li><p>当有新消息通过 PUBLISH 命令发送给频道 channel1 时， 这个消息就会被发送给订阅它的三个客户端：</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/10187/20200601220942.webp" alt="img"></p></li></ul><h4 id="发布订阅命令"><a href="#发布订阅命令" class="headerlink" title="发布订阅命令"></a>发布订阅命令</h4><table><thead><tr><th>序号</th><th>命令及描述</th></tr></thead><tbody><tr><td>1</td><td>PSUBSCRIBE pattern [pattern …]  订阅一个或多个符合给定模式的频道。</td></tr><tr><td>2</td><td>PUBSUB subcommand [argument [argument …]] 查看订阅与发布系统状态。</td></tr><tr><td>3</td><td><code>PUBLISH</code> channel message将信息发送到指定的频道。</td></tr><tr><td>4</td><td>PUNSUBSCRIBE [pattern [pattern …]] 退订所有给定模式的频道。</td></tr><tr><td>5</td><td><code>SUBSCRIBE</code> channel [channel …]订阅给定的一个或多个频道的信息。</td></tr><tr><td>6</td><td>UNSUBSCRIBE [channel [channel …]]指退订给定的频道。</td></tr></tbody></table><h4 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h4><ol><li><p>可以一次性订阅多个</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SUBSCRIBE c1 c2 c3</span><br></pre></td></tr></table></figure></li><li><p>消息发布</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PUBLISH c1 helloredis</span><br></pre></td></tr></table></figure></li><li><p>订阅多个可以使用通配符*</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PSUBSCRIBE new*</span><br></pre></td></tr></table></figure></li><li><p>接收消息</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">PUBLISH new1 redis2018</span><br><span class="line">PUBLISH new2 redis2018</span><br></pre></td></tr></table></figure></li></ol><h2 id="主从复制"><a href="#主从复制" class="headerlink" title="主从复制"></a>主从复制</h2><p>在Redis中，用户可以通过执行SLAVEOF命令或者设置slaveof选项，让一个服务器去复制（replicate）另一个服务器，我们称呼被复制的服务器为主服务器（master），而对主服务器进行复制的服务器则被称为从服务器（slave）。通常用作读写分离，以及数据恢复。</p><h4 id="配置主从"><a href="#配置主从" class="headerlink" title="配置主从"></a>配置主从</h4><h5 id="认主："><a href="#认主：" class="headerlink" title="认主："></a>认主：</h5><p>在从库里使用slaveof命令，从库认主后，从库只能做读操作;</p><p>当主机挂求后，从机原地待命；</p><p>当从机挂求重启后，从机变主机；</p><p>当使用redis.conf认主，不使用命令配置认主。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">slaveof host port # 认主</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">info [section] # 查看redis信息（带replication参数可直接看主从信息）</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SLAVEOF no one # 将从库转成主库，并保已有数据</span><br></pre></td></tr></table></figure><h4 id="哨兵模式"><a href="#哨兵模式" class="headerlink" title="哨兵模式"></a>哨兵模式</h4><p>Redis的主从架构，如果master发现故障了，还得手动将slave切换成master继续服务，手动的方式容易造成失误，导致数据丢失，那Redis有没有一种机制可以在master和slave进行监控，并在master发送故障的时候，能自动将slave切换成master呢？有的，那就是哨兵。</p><h5 id="哨兵的作用："><a href="#哨兵的作用：" class="headerlink" title="哨兵的作用："></a>哨兵的作用：</h5><ol><li>监控redis进行状态，包括master和slave </li><li>当master down机，能自动将slave切换成master</li></ol><h5 id="配置哨兵："><a href="#配置哨兵：" class="headerlink" title="配置哨兵："></a>配置哨兵：</h5><p>新建配置文件，命名为sentinel.conf，输入下面内容</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sentinel monitor mymaster 192.168.137.101 6379 1</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">sentinel auth-pass myMaster master123 <span class="comment"># 配置密码</span></span></span><br></pre></td></tr></table></figure><p>mymaster ：master服务的名称，随便定义 </p><h5 id="启动哨兵："><a href="#启动哨兵：" class="headerlink" title="启动哨兵："></a>启动哨兵：</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-sentinel sentinel.conf</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">include /path/to/other.conf 这在你有标准配置模板但是每个redis服务器又需要个性设置的时候很有用，aemonize yes Redis 默认不是以守护进程的方式运行，可以通过该配置项修改</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Redis" scheme="https://blog.imzjw.cn/tags/Redis/"/>
    
  </entry>
  
  <entry>
    <title>Redis数据类型</title>
    <link href="https://blog.imzjw.cn/posts/1ab2/"/>
    <id>https://blog.imzjw.cn/posts/1ab2/</id>
    <published>2020-06-01T09:08:35.000Z</published>
    <updated>2020-06-01T09:08:35.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Redis-的五大数据类型"><a href="#Redis-的五大数据类型" class="headerlink" title="Redis 的五大数据类型"></a>Redis 的五大数据类型</h2><ol><li>string（字符串）</li><li>hash（哈希，类似 java 里的Map）</li><li>list（列表）</li><li>set（集合）</li><li>zset (sorted set：有序集合)</li></ol><h3 id="String"><a href="#String" class="headerlink" title="String"></a>String</h3><p>String 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如 jpg 图片或者序列化的对象 。string 类型是 Redis 最基本的数据类型，一个 redis 中字符串 value 最多可以是 512 M。String 数据结构是简单的 key-value 类型，value 其实不仅是 String，也可以是数字.    </p><h4 id="应用场景："><a href="#应用场景：" class="headerlink" title="应用场景："></a>应用场景：</h4><p>String 是最常用的一种数据类型，普通的 key / value 存储都可以归为此类.即可以完全实现目前 Memcached 的功能，并且效率更高。还可以享受 Redis 的定时持久化，操作日志及 Replication等功能。</p><h4 id="常用命令："><a href="#常用命令：" class="headerlink" title="常用命令："></a>常用命令：</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">set key value # 赋值</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">get key # 取值</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">del key # 删除(可以多个)</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">append key # 追加</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">exists key # 判断某个key是否存在，1表示存在，0表示不存在</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">strlen key # 返回长度</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">move key db # 移动索引库，例如：move key1 5   将当前库中的key1移5号库</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">expire key 秒钟 # 为指定的key设置过期时间</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ttl key # 查看还有多少秒过期，-1表示永不过期，-2表示已过期</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">type key # 查看你的key是什么类型</span><br></pre></td></tr></table></figure><h4 id="数字值命令："><a href="#数字值命令：" class="headerlink" title="数字值命令："></a>数字值命令：</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">incr key # 将key中储存的数字值增一</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">decr key # 将key中储存的数字值减一</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">incrby key # 将key所储存的值加上给定的增量值（increment） </span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">decrby key # 将key所储存的值减去给定的减量值（decrement） </span><br></pre></td></tr></table></figure><h4 id="其它命令："><a href="#其它命令：" class="headerlink" title="其它命令："></a>其它命令：</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">getrange key startindex endindex # 获取指定区间值(0到-1获取全部)</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">setrange key startindex endindex # 设置指定区间值</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">setex key time(秒) # value 将值value关联到key，并将key的过期时间设为seconds(以秒为单位)</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">setnx key value # 只有在key不存在时设置 key 的值，如果已经存在则不设置值</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mset key value [key2 value2 ...] # 同时设置一个或多个键值对</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mget key [key2 key3 ...] # 获取所有(一个或多个)给定key的值</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">msetnx key value [key2 value2 ...]  # 同时设置一个或多个键值对（key不存在时）在设置的过程中只要有一个失败，其他的都不会set成功</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">getset key value # 获取旧值，设置新值</span><br></pre></td></tr></table></figure><h4 id="Java-实例"><a href="#Java-实例" class="headerlink" title="Java 实例"></a>Java 实例</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> redis.clients.jedis.Jedis;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RedisStringJava</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 连接本地的 Redis 服务</span></span><br><span class="line">        <span class="type">Jedis</span> <span class="variable">jedis</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Jedis</span>(<span class="string">&quot;106.55.2.41&quot;</span>, <span class="number">6379</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;连接成功&quot;</span>);</span><br><span class="line">        <span class="comment">// 设置 redis 字符串数据</span></span><br><span class="line">        jedis.set(<span class="string">&quot;garvey&quot;</span>, <span class="string">&quot;nizhenshuai&quot;</span>);</span><br><span class="line">        <span class="comment">// 获取存储的数据并输出</span></span><br><span class="line">        System.out.println(<span class="string">&quot;redis 存储的字符串为: &quot;</span> + jedis.get(<span class="string">&quot;garvey&quot;</span>));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译以上程序。 </p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">连接成功</span><br><span class="line">redis 存储的字符串为: nizhenshuai</span><br></pre></td></tr></table></figure><h4 id="EXPIRE命令业务场景"><a href="#EXPIRE命令业务场景" class="headerlink" title="EXPIRE命令业务场景"></a>EXPIRE命令业务场景</h4><div class="note warning flat"><p>EXPIRE key second的使用场景：</p><ol><li>限时的优惠活动 </li><li>网站数据缓存 </li><li>手机验证码 </li><li>限制网站访客频率</li></ol></div><h4 id="key的命名建议"><a href="#key的命名建议" class="headerlink" title="key的命名建议"></a>key的命名建议</h4><ol><li>key 不要太长，尽量不要超过 1024 字节。不仅消耗内存，也会降低查找的效率</li><li>key 不要太短，太短可读性会降低</li><li>在一个项目中，key 最好使用统一的命名模式，如 user:123:password</li><li>key 区分大小写</li></ol><h4 id="String-应用场景："><a href="#String-应用场景：" class="headerlink" title="String 应用场景："></a>String 应用场景：</h4><div class="note warning flat"><ol><li>String 通常用于保存单个字符串或 JSON 字符串数据 </li><li>因为 String 是二进制安全的，所以可以把保密要求高的图片文件内容作为字符串来存储 </li><li>计数器：常规 Key-Value 缓存应用，如微博数、粉丝数。INCR 本身就具有原子性特性，所以不会有线程安全问题</li></ol></div><hr><h3 id="List"><a href="#List" class="headerlink" title="List"></a>List</h3><p>Redis 列表是简单的字符串列表，按照插入顺序排序。你可以添加一个元素导列表的头部（左边）或者尾部（右边）。它的底层实际是个链表。</p><h4 id="应用场景：-1"><a href="#应用场景：-1" class="headerlink" title="应用场景："></a>应用场景：</h4><p>Redis list的应用场景非常多，也是Redis最重要的数据结构之一，比如twitter的关注列表，粉丝列表等都可以用Redis的list结构来实现。Lists 就是链表，相信略有数据结构知识的人都应该能理解其结构。使用Lists结构，我们可以轻松地实现最新消息排行等功能。Lists的另一个应用就是消息队列，</p><p>可以利用Lists的PUSH操作，将任务存在Lists中，然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作Lists中某一段的api，你可以直接查询，删除Lists中某一段的元素。</p><h4 id="项目应用场景"><a href="#项目应用场景" class="headerlink" title="项目应用场景"></a>项目应用场景</h4><div class="note warning flat"><ol><li>对数据大的集合数据删减     列表显示、关注列表、粉丝列表、留言评价…分页、热点新闻等 </li><li>任务队列     list通常用来实现一个消息队列，而且可以确保先后顺序，不必像MySQL那样通过order by来排序</li></ol></div><h4 id="基本命令："><a href="#基本命令：" class="headerlink" title="基本命令："></a>基本命令：</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lpush key value [value2 ...] # 将一个或多个值插入到列表头部(允许值重复)</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rpush key value [value2 ...] # 将一个或多个值插入到列表尾部(允许值重复)</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lrange key startindex endindex # 获取列表指定范围内的元素(0到-1获取全部)</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lindex key index # 通过索引获取列表中的元素</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">llen key # 获取指定key值的个数</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lpop key # 移出并获取列表的第一个元素</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rpop key # 移除并获取列表最后一个元素</span><br></pre></td></tr></table></figure><h4 id="其他命令："><a href="#其他命令：" class="headerlink" title="其他命令："></a>其他命令：</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lrem key count value # 删除count个value</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ltrim key start end # 截取指定范围的值后再赋值给key（让列表只保留指定区间内的元素，不在指定区间之内的元素都将被删除）</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lset key index value # 通过索引设置列表元素的值</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">linsert key BEFORE|AFTER pivot value # 在列表指定的元素前或者后插入元素</span><br></pre></td></tr></table></figure><h4 id="Java-实例-1"><a href="#Java-实例-1" class="headerlink" title="Java 实例"></a>Java 实例</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"><span class="keyword">import</span> redis.clients.jedis.Jedis;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RedisListJava</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 连接本地的 Redis 服务</span></span><br><span class="line">        <span class="type">Jedis</span> <span class="variable">jedis</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Jedis</span>(<span class="string">&quot;106.55.2.41&quot;</span>, <span class="number">6379</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;连接成功&quot;</span>);</span><br><span class="line">        <span class="comment">// 存储数据到列表中</span></span><br><span class="line">        jedis.lpush(<span class="string">&quot;site-list&quot;</span>, <span class="string">&quot;garvey&quot;</span>);</span><br><span class="line">        jedis.lpush(<span class="string">&quot;site-list&quot;</span>, <span class="string">&quot;Google&quot;</span>);</span><br><span class="line">        jedis.lpush(<span class="string">&quot;site-list&quot;</span>, <span class="string">&quot;Taobao&quot;</span>);</span><br><span class="line">        <span class="comment">// 获取存储的数据并输出</span></span><br><span class="line">        List&lt;String&gt; list = jedis.lrange(<span class="string">&quot;site-list&quot;</span>, <span class="number">0</span>, <span class="number">2</span>);</span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; list.size(); i++) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;列表项为: &quot;</span> + list.get(i));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译以上程序。 </p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">连接成功</span><br><span class="line">列表项为: Taobao</span><br><span class="line">列表项为: Google</span><br><span class="line">列表项为: garvey</span><br></pre></td></tr></table></figure><h4 id="性能总结"><a href="#性能总结" class="headerlink" title="性能总结"></a>性能总结</h4><ul><li>它是一个字符串链表，left、right都可以插入和添加</li><li>如果键不存在，创建新的链表，如果键已经存在，新增内容，如果值全部移除，对应的键也消失了</li><li>链表的操作无论是对头和尾效率都极高，但假如是对中间元素进行操作，效率就很惨淡了</li></ul><h3 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h3><p>Set是string类型的无序集合。它是通过HashTable实现实现的。</p><h4 id="应用场景：-2"><a href="#应用场景：-2" class="headerlink" title="应用场景："></a>应用场景：</h4><p>Redis set对外提供的功能与list类似是一个列表的功能，特殊之处在于set是可以自动排重的，当你需要存储一个列表数据，又不希望出现重复数据时，set是一个很好的选择，并且set提供了判断某个成员是否在一个set集合内的重要接口，这个也是list所不能提供的。Sets 集合的概念就是一堆不重复值的组合。利用Redis提供的Sets数据结构，可以存储一些集合性的数据，比如在微博应用中，可以将一个用户所有的关注人存在一个集合中，将其所有粉丝存在一个集合。Redis还为集合提供了求交集、并集、差集等操作，可以非常方便的实现如共同关注、共同喜好、二度好友等功能，对上面的所有集合操作，你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。</p><h4 id="基本命令：-1"><a href="#基本命令：-1" class="headerlink" title="基本命令："></a>基本命令：</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sadd key value [value2 ...] # 向集合添加一个或多个成员</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">smembers key # 返回集合中的所有成员</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sismember key member # 判断 member 元素是否是集合 key 的成员</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">scard key # 获取集合里面的元素个数</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">srem key value # 删除集合中指定元素</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">spop key [count] # 移除集合中一个随机元素并返这个元素（可选择删除数量）</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">srandmember key [coutn] # 随机返回集合中一个或多个值</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">smove key1 key2 # 将key1里的某个值赋给key2</span><br></pre></td></tr></table></figure><h4 id="其他命令：-1"><a href="#其他命令：-1" class="headerlink" title="其他命令："></a>其他命令：</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sdiff key1 [key2] # 返回给定所有集合的差集</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sinter key1 [key2] # 返回给定所有集合的交集</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sunion key1 [key2] 返回所有给定集合的并集</span><br></pre></td></tr></table></figure><h4 id="项目场景"><a href="#项目场景" class="headerlink" title="项目场景"></a>项目场景</h4><div class="note info flat"><p>对两个集合间的数据[计算]进行交集、并集、差集运算 </p><ol><li>以非常方便的实现如共同关注、共同喜好、二度好友等功能。对上面的所有集合操作，你还可以使用不同的命令选择将结果返回给客户端还是存储到一个新的集合中。 </li><li>利用唯一性，可以统计访问网站的所有独立 IP</li></ol></div><h3 id="Hash"><a href="#Hash" class="headerlink" title="Hash"></a>Hash</h3><p>Redis hash 是一个键值对集合。hash是一个string类型的field和value的映射表，hash特别适合用于存储对象。类似Java里面的Map&lt;String,Object&gt;。</p><h4 id="应用场景：-3"><a href="#应用场景：-3" class="headerlink" title="应用场景："></a>应用场景：</h4><p>在Memcached中，我们经常将一些结构化的信息打包成HashMap，在客户端序列化后存储为一个字符串的值，比如用户的昵称、年龄、性别、积分等，这时候在需要修改其中某一项时，通常需要将所有值取出反序列化后，修改某一项的值，再序列化存储回去。<strong>这样不仅增大了开销，也不适用于一些可能并发操作的场合</strong>（比如两个并发的操作都需要修改积分）。而Redis的Hash结构可以使你像在数据库中Update一个属性一样只修改某一项属性值。 </p><h4 id="项目应用场景-1"><a href="#项目应用场景-1" class="headerlink" title="项目应用场景"></a>项目应用场景</h4><div class="note warning flat"><p>Hash的应用场景，通常用来存储一个用户信息的对象数据。 </p><ol><li>相比于存储对象的string类型的json串，json串修改单个属性需要将整个值取出来。而hash不需要。 </li><li>相比于多个key-value存储对象，hash节省了很多内存空间 </li><li>如果hash的属性值被删除完，那么hash的key也会被redis删除</li></ol></div><h4 id="基本命令：-2"><a href="#基本命令：-2" class="headerlink" title="基本命令："></a>基本命令：</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hset key field value # 以hash方式存储</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hget key field # 以hash方式获取</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hmset key field value # [field value ...] 以hash方式存储一个或者多个</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hmget key field # [field ...] 以hash方式获取一个或者多个</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hgetall key # 获取在哈希表中指定key的所有字段和值</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hdel key field [field ...] # 删除一个或多个哈希表字段</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hkeys key # 获取所有哈希表中的字段</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hvals key # 获取哈希表中所有值</span><br></pre></td></tr></table></figure><h4 id="其他命令：-2"><a href="#其他命令：-2" class="headerlink" title="其他命令："></a>其他命令：</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hlen key # 获取哈希表中字段的数量</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexists key # 查看哈希表key中，指定的字段是否存在</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hincrby key field value # 为哈希表key中的指定字段的整数值加上增量value(必须为数字)</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hincrbyfloat key field value # 为哈希表key中的指定字段的浮点数值加上增量value </span><br></pre></td></tr></table></figure><h4 id="Java-实例-2"><a href="#Java-实例-2" class="headerlink" title="Java 实例"></a>Java 实例</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Iterator;</span><br><span class="line"><span class="keyword">import</span> java.util.Set;</span><br><span class="line"><span class="keyword">import</span> redis.clients.jedis.Jedis;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RedisKeyJava</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 连接本地的 Redis 服务</span></span><br><span class="line">        <span class="type">Jedis</span> <span class="variable">jedis</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Jedis</span>(<span class="string">&quot;106.55.2.41&quot;</span>, <span class="number">6379</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;连接成功&quot;</span>);</span><br><span class="line"> </span><br><span class="line">        <span class="comment">// 获取数据并输出</span></span><br><span class="line">        Set&lt;String&gt; keys = jedis.keys(<span class="string">&quot;*&quot;</span>); </span><br><span class="line">        Iterator&lt;String&gt; it = keys.iterator() ;   </span><br><span class="line">        <span class="keyword">while</span>(it.hasNext())&#123;   </span><br><span class="line">            <span class="type">String</span> <span class="variable">key</span> <span class="operator">=</span> it.next();   </span><br><span class="line">            System.out.println(key);   </span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>编译以上程序。 </p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">连接成功</span><br><span class="line">garvey</span><br></pre></td></tr></table></figure><h3 id="Zset"><a href="#Zset" class="headerlink" title="Zset"></a>Zset</h3><p>zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。</p><h4 id="应用场景：-4"><a href="#应用场景：-4" class="headerlink" title="应用场景："></a>应用场景：</h4><p>Redis sorted set的使用场景与set类似，区别是set不是自动有序的，而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序，并且是插入有序的，即自动排序。当你需要一个有序的并且不重复的集合列表，那么可以选择sorted set数据结构，比如twitter 的public timeline可以以发表时间作为score来存储，这样获取时就是自动按时间排好序的。还可以用Sorted Sets来做带权重的队列，比如普通消息的score为1，重要消息的score为2，然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。</p><h4 id="基本命令：-3"><a href="#基本命令：-3" class="headerlink" title="基本命令："></a>基本命令：</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zadd key score1 member1 [score2 member2] # 向有序集合添加一个或多个成员，或者更新已存在成员的分数</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zrange key startindex endindex [WITHSCORES] # 通过索引区间返回有序集合成指定区间内的成员(WITHSCORES带出分数)</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zscore key member # 返回有序集中，成员的分数值</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zrangebyscore key min max [WITHSCORES] [LIMIT] # 通过分数返回有序集合指定区间内的成员</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zrem key member [member ...] # 删除一个或多个元素</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zcard key # 获取有序集合的成员数</span><br></pre></td></tr></table></figure><h4 id="其他命令：-3"><a href="#其他命令：-3" class="headerlink" title="其他命令："></a>其他命令：</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zcount key min max # 计算在有序集合中指定区间分数的成员数</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zrank key member # 返回有序集合中指定成员的索引</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zrevrank key member # 返回有序集合中指定成员的排名，有序集成员按分数值递减(从大到小)排序</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zrevrange key startindex endindex [WITHSCORES] # 返回有序集中指定区间内的成员，通过索引，分数从高到底</span><br></pre></td></tr></table></figure><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zrevrangebyscore key max min [WITHSCORES] # 返回有序集中指定分数区间内的成员，分数从高到低排序</span><br></pre></td></tr></table></figure><h4 id="项目场景-1"><a href="#项目场景-1" class="headerlink" title="项目场景"></a>项目场景</h4><div class="note warning flat"><p>常用于排行榜： </p><ol><li>如推特可以以发表时间作为score来存储</li><li>存储成绩 </li><li>还可以用zset来做带权重的队列，让重要的任务先执行</li></ol></div>]]></content>
    
    
    <summary type="html">Redis 的五大数据类型：1.string（字符串）2.hash（哈希，类似java里的Map）3.list（列表）4.set（集合）5.zset(sorted set：有序集合)</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Redis" scheme="https://blog.imzjw.cn/tags/Redis/"/>
    
  </entry>
  
  <entry>
    <title>电脑重装系统后如何恢复Hexo博客</title>
    <link href="https://blog.imzjw.cn/posts/cd97/"/>
    <id>https://blog.imzjw.cn/posts/cd97/</id>
    <published>2020-05-27T14:03:08.000Z</published>
    <updated>2020-05-27T14:03:08.000Z</updated>
    
    <content type="html"><![CDATA[<p>不废话了，直接开始</p><h2 id="安装环境"><a href="#安装环境" class="headerlink" title="安装环境"></a>安装环境</h2><p>安装 <code>Node.js</code>，<code>Git</code></p><p>并查看当前软件环境</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cd97/20200527220636.webp" alt="img"></p><p>配置 <code>SSH key</code></p><p>查看 <code>C:\Users\用户名\.ssh</code> 下有无 ssh 文件夹，没有则创建</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd ~/. ssh</span><br><span class="line">ssh-keygen -t rsa -C &quot;邮件地址&quot;</span><br></pre></td></tr></table></figure><p>打开用户目录，找到 <code>.ssh\id_rsa.pub</code> 文件，用编辑器打开并复制里面的内容</p><p>然后打开你的 Github or Gitee 主页，进入个人设置 -&gt; SSH公钥 -&gt; 添加公钥</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cd97/20200527221110.webp" alt="img"></p><p>测试是否成功</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">github输入此命令</span></span><br><span class="line">ssh -T git@github.com</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">gitee输入此命令</span></span><br><span class="line">ssh -T git@gitee.com</span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cd97/20200527221314.webp" alt="img"></p><p>用户名 邮箱配置</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git config --global user.name &quot;xxx&quot;  # 你的gitee(github)用户名，非昵称</span><br><span class="line">git config --global user.email &quot;xxx@gmail.com&quot;  # 填写你的gitee(github)注册邮箱</span><br></pre></td></tr></table></figure><p>进入到博客根目录删除<code>node_modules</code>   <code>public</code>     <code>.git</code>   <code>.deploy_git</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cd97/20200527221709.webp" alt="img"></p><p>关联 <code>GitHub</code>项目</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git init</span><br><span class="line">git remote add origin git@github.com:xxx/xxx.git # 关联你的项目</span><br></pre></td></tr></table></figure><p>运行如下指令 <code>npm install -g hexo-cli</code> 安装hexo</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g hexo-cli</span><br></pre></td></tr></table></figure><p>运行如下指令安装项目依赖</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install</span><br></pre></td></tr></table></figure><p>最后 <code>hexo g &amp;&amp; hexo s</code> 生成并本地预览</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cd97/20200527223000.webp" alt="img"></p><p>在浏览器中输入 <code>localhost:4000</code> 大功告成</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/cd97/myblog.webp" alt="img"></p>]]></content>
    
    
    <summary type="html">安装环境，安装 Node.js，Git，并查看当前软件环境，配置 SSH key，查看用户下有无ssh文件夹，没有则创建，打开用户目录，找到 id_rsa.pub 文件，用编辑器打开并复制里面的内容</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>Docker常用命令</title>
    <link href="https://blog.imzjw.cn/posts/7569/"/>
    <id>https://blog.imzjw.cn/posts/7569/</id>
    <published>2020-05-26T02:38:46.000Z</published>
    <updated>2020-05-26T02:38:46.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Docker-容器信息"><a href="#Docker-容器信息" class="headerlink" title="Docker 容器信息"></a>Docker 容器信息</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">查看 docker 容器版本</span></span><br><span class="line">docker version</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">查看 docker 容器信息</span></span><br><span class="line">docker info</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">查看 docker 容器帮助</span></span><br><span class="line">docker --help</span><br></pre></td></tr></table></figure><h2 id="镜像操作"><a href="#镜像操作" class="headerlink" title="镜像操作"></a>镜像操作</h2><p>提示：对于镜像的操作可使用镜像名、镜像长ID和短ID。</p><h3 id="镜像查看"><a href="#镜像查看" class="headerlink" title="镜像查看"></a>镜像查看</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">列出本地images</span></span><br><span class="line">docker images</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">含中间映像层</span></span><br><span class="line">docker images -a</span><br></pre></td></tr></table></figure><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7569/20200526144706.webp" alt="img"><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">只显示镜像ID docker images -q <span class="comment">#含中间映像层 docker images -qa</span></span></span><br></pre></td></tr></table></figure><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7569/20200526144811.webp" alt="img"><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">显示镜像摘要信息(DIGEST列)</span></span><br><span class="line">docker images --digests</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">显示镜像完整信息</span></span><br><span class="line">docker images --no-trunc</span><br></pre></td></tr></table></figure><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7569/20200526144848.webp" alt="img"><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">显示指定镜像的历史创建；参数：-H 镜像大小和日期，默认为<span class="literal">true</span>；--no-trunc  显示完整的提交记录；-q  仅列出提交记录ID</span></span><br><span class="line">docker history -H redis</span><br></pre></td></tr></table></figure><p>镜像搜索</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">搜索仓库MySQL镜像</span></span><br><span class="line">docker search mysql</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">--filter=stars=600：只显示 starts&gt;=600 的镜像</span></span><br><span class="line">docker search --filter=stars=600 mysql</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">--no-trunc 显示镜像完整 DESCRIPTION 描述</span></span><br><span class="line">docker search --no-trunc mysql</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">--automated ：只列出 AUTOMATED=OK 的镜像</span></span><br><span class="line">docker search  --automated mysql</span><br></pre></td></tr></table></figure><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7569/20200526145015.webp" alt="img"><h3 id="镜像下载"><a href="#镜像下载" class="headerlink" title="镜像下载"></a>镜像下载</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">下载Redis官方最新镜像，相当于：docker pull redis:latest</span></span><br><span class="line">docker pull redis</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">下载仓库所有Redis镜像</span></span><br><span class="line">docker pull -a redis</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">下载私人仓库镜像</span></span><br><span class="line">docker pull bitnami/redis</span><br></pre></td></tr></table></figure><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7569/20200526145035.webp" alt="img"><h3 id="镜像删除"><a href="#镜像删除" class="headerlink" title="镜像删除"></a>镜像删除</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">单个镜像删除，相当于：docker rmi redis:latest</span></span><br><span class="line">docker rmi redis</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">强制删除(针对基于镜像有运行的容器进程)</span></span><br><span class="line">docker rmi -f redis</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">多个镜像删除，不同镜像间以空格间隔</span></span><br><span class="line">docker rmi -f redis tomcat nginx</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">删除本地全部镜像</span></span><br><span class="line">docker rmi -f $(docker images -q)</span><br></pre></td></tr></table></figure><h3 id="镜像构建"><a href="#镜像构建" class="headerlink" title="镜像构建"></a>镜像构建</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">（1）编写dockerfile</span></span><br><span class="line">cd /docker/dockerfile</span><br><span class="line">vim mycentos</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">（2）构建docker镜像</span></span><br><span class="line">docker build -f /docker/dockerfile/mycentos -t mycentos:1.1</span><br></pre></td></tr></table></figure><h2 id="容器操作"><a href="#容器操作" class="headerlink" title="容器操作"></a>容器操作</h2><blockquote><p>提示：对于容器的操作可使用CONTAINER ID 或 NAMES。</p></blockquote><h3 id="容器启动"><a href="#容器启动" class="headerlink" title="容器启动"></a>容器启动</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">新建并启动容器，参数：-i  以交互模式运行容器；-t  为容器重新分配一个伪输入终端；--name  为容器指定一个名称</span></span><br><span class="line">docker run -i -t --name mycentos</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">后台启动容器，参数：-d  已守护方式启动容器</span></span><br><span class="line">docker run -d mycentos</span><br></pre></td></tr></table></figure><div class="note warning flat"><p>注意：此时使用”docker ps -a”会发现容器已经退出。这是docker的机制：要使Docker容器后台运行，就必须有一个前台进程。解决方案：将你要运行的程序以前台进程的形式运行。</p></div><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">启动一个或多个已经被停止的容器</span></span><br><span class="line">docker start redis</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">重启容器</span></span><br><span class="line">docker restart redis</span><br></pre></td></tr></table></figure><h3 id="容器进程"><a href="#容器进程" class="headerlink" title="容器进程"></a>容器进程</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">top支持 ps 命令参数，格式：docker top [OPTIONS] CONTAINER [ps OPTIONS]</span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">列出redis容器中运行进程</span></span><br><span class="line">docker top redis</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">查看所有运行容器的进程信息</span></span><br><span class="line">for i in  `docker ps |grep Up|awk &#x27;&#123;print $1&#125;&#x27;`;do echo \ &amp;&amp;docker top $i; done</span><br></pre></td></tr></table></figure><h3 id="容器日志"><a href="#容器日志" class="headerlink" title="容器日志"></a>容器日志</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">查看redis容器日志，默认参数</span></span><br><span class="line">docker logs rabbitmq</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">查看redis容器日志，参数：-f  跟踪日志输出；-t   显示时间戳；--<span class="built_in">tail</span>  仅列出最新N条容器日志；</span></span><br><span class="line">docker logs -f -t --tail=20 redis</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">查看容器redis从2019年05月21日后的最新10条日志。</span></span><br><span class="line">docker logs --since=&quot;2019-05-21&quot; --tail=10 redis</span><br></pre></td></tr></table></figure><h3 id="容器的进入与退出"><a href="#容器的进入与退出" class="headerlink" title="容器的进入与退出"></a>容器的进入与退出</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">使用run方式在创建时进入</span></span><br><span class="line">docker run -it centos /bin/bash</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">关闭容器并退出</span></span><br><span class="line">exit</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">仅退出容器，不关闭</span></span><br><span class="line">快捷键：Ctrl + P + Q</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">直接进入centos 容器启动命令的终端，不会启动新进程，多个attach连接共享容器屏幕，参数：--sig-proxy=<span class="literal">false</span>  确保CTRL-D或CTRL-C不会关闭容器</span></span><br><span class="line">docker attach --sig-proxy=false centos </span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">在 centos 容器中打开新的交互模式终端，可以启动新进程，参数：-i  即使没有附加也保持STDIN 打开；-t  分配一个伪终端</span></span><br><span class="line">docker exec -i -t  centos /bin/bash</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">以交互模式在容器中执行命令，结果返回到当前终端屏幕</span></span><br><span class="line">docker exec -i -t centos ls -l /tmp</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">以分离模式在容器中执行命令，程序后台运行，结果不会反馈到当前终端</span></span><br><span class="line">docker exec -d centos  touch cache.txt </span><br></pre></td></tr></table></figure><h3 id="查看容器"><a href="#查看容器" class="headerlink" title="查看容器"></a>查看容器</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">查看正在运行的容器</span></span><br><span class="line">docker ps</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">查看正在运行的容器的ID</span></span><br><span class="line">docker ps -q</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">查看正在运行+历史运行过的容器</span></span><br><span class="line">docker ps -a</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">显示运行容器总文件大小</span></span><br><span class="line">docker ps -s</span><br></pre></td></tr></table></figure><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7569/20200526145056.webp" alt="img"><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">显示最近创建容器</span></span><br><span class="line">docker ps -l</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">显示最近创建的3个容器</span></span><br><span class="line">docker ps -n 3</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">不截断输出</span></span><br><span class="line">docker ps --no-trunc </span><br></pre></td></tr></table></figure><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/7569/20200526145121.webp" alt="img"><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">获取镜像redis的元信息</span></span><br><span class="line">docker inspect redis</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">获取正在运行的容器redis的 IP</span></span><br><span class="line">docker inspect --format=&#x27;&#123;&#123;range .NetworkSettings.Networks&#125;&#125;&#123;&#123;.IPAddress&#125;&#125;&#123;&#123;end&#125;&#125;&#x27; redis</span><br></pre></td></tr></table></figure><h3 id="容器的停止与删除"><a href="#容器的停止与删除" class="headerlink" title="容器的停止与删除"></a>容器的停止与删除</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">停止一个运行中的容器</span></span><br><span class="line">docker stop redis</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">杀掉一个运行中的容器</span></span><br><span class="line">docker kill redis</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">删除一个已停止的容器</span></span><br><span class="line">docker rm redis</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">删除一个运行中的容器</span></span><br><span class="line">docker rm -f redis</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">删除多个容器</span></span><br><span class="line">docker rm -f $(docker ps -a -q)</span><br><span class="line">docker ps -a -q | xargs docker rm</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">-l 移除容器间的网络连接，连接名为 db</span></span><br><span class="line">docker rm -l db </span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">-v 删除容器，并删除容器挂载的数据卷</span></span><br><span class="line">docker rm -v redis</span><br></pre></td></tr></table></figure><h3 id="生成镜像"><a href="#生成镜像" class="headerlink" title="生成镜像"></a>生成镜像</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">基于当前redis容器创建一个新的镜像；参数：-a 提交的镜像作者；-c 使用Dockerfile指令来创建镜像；-m :提交时的说明文字；-p :在commit时，将容器暂停</span></span><br><span class="line">docker commit -a=&quot;DeepInThought&quot; -m=&quot;my redis&quot; [redis容器ID]  myredis:v1.1</span><br></pre></td></tr></table></figure><h3 id="容器与主机间的数据拷贝"><a href="#容器与主机间的数据拷贝" class="headerlink" title="容器与主机间的数据拷贝"></a>容器与主机间的数据拷贝</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">将rabbitmq容器中的文件copy至本地路径</span></span><br><span class="line">docker cp rabbitmq:/[container_path] [local_path]</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">将主机文件copy至rabbitmq容器</span></span><br><span class="line">docker cp [local_path] rabbitmq:/[container_path]/</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">将主机文件copy至rabbitmq容器，目录重命名为[container_path]（注意与非重命名copy的区别）</span></span><br><span class="line">docker cp [local_path] rabbitmq:/[container_path]</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">Docker 容器信息-查看docker容器版本 docker version，查看docker容器信息 docker info，查看docker容器帮助 docker --help</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Docker" scheme="https://blog.imzjw.cn/tags/Docker/"/>
    
  </entry>
  
  <entry>
    <title>GitHub+jsDelivr+PicGo搭建免费图床</title>
    <link href="https://blog.imzjw.cn/posts/fb2a/"/>
    <id>https://blog.imzjw.cn/posts/fb2a/</id>
    <published>2020-05-25T09:23:36.000Z</published>
    <updated>2020-05-25T09:23:36.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><ol><li><p>用 markdown 写博客，想插入一些图片，如果采用本地存储方式，上传博客时插入的图片路径就找不到了，需要手动再把图片上传上去，并且修改路径，很麻烦，可以考虑将图片上传至图床生成 URL，直接在 markdown 引入url。</p></li><li><p>现在国内用的各种图床，例如微博图床、SM.MS、Imgur、七牛云、又拍云、腾讯云 COS、阿里云 OSS 等都有各种限制，或者需要收费。</p></li><li><p>使用 GitHub 仓库创建一个图床，存在的问题是国内访问 github 的速度不是很快，但是我们可以利用 jsDelivr CDN 加速访问</p></li></ol><h2 id="创建-Github-仓库"><a href="#创建-Github-仓库" class="headerlink" title="创建 Github 仓库"></a>创建 Github 仓库</h2><p>创建一个 github 仓库，专门存放上传的图片。</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fb2a/20200526150555.webp" alt="img"/><div class="note warning flat"><p>如果还没 github 账号的请 <a href="https://github.com/">注册</a></p></div><h2 id="生成-Access-Token"><a href="#生成-Access-Token" class="headerlink" title="生成 Access Token"></a>生成 Access Token</h2><p>按照下列步骤依次生成 Token，生成的 Token 只显示一次，页面关闭后就看不了了，需要先将它复制下来</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fb2a/github.webp" alt="图1"/><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fb2a/6de52523cfc8a.webp" alt="图2"/><h2 id="配置-PicGo"><a href="#配置-PicGo" class="headerlink" title="配置 PicGo"></a>配置 PicGo</h2><p>下载 PicGo</p><div class="btns rounded grid5">            <a class="button" href='https://github.com/Molunerfinn/picgo/releases' title='下载地址'><i class='fas fa-download'></i>下载地址</a>          </div><p>打开 PicGo 进行配置</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fb2a/20200526150650.webp" alt="img"/><ol><li>设定仓库名：按照【用户名 / 图床仓库名】的格式填写</li><li>设定分支名：【 master 】</li><li>设定 Token：粘贴上述生成的【 Token 】</li><li>指定存储路径：填写想要储存的路径，如【 img/ 】，这样就会在仓库下创建一个名为 img 的文件夹，图片将会储存在此文件夹中</li><li>设定自定义域名：它的的作用是，在图片上传后，PicGo 会按照【 自定义域名 + 上传的图片名 】的方式生成访问链接，放到粘贴板上，因为我们要使用 jsDelivr 加速访问，所以可以设置为 <code>https://cdn.jsdelivr.net/gh/用户名/图床仓库名</code></li></ol><p>至此搭建完毕 然后就可以直接上传了</p>]]></content>
    
    
    <summary type="html">用 markdown 写博客，想插入一些图片，如果采用本地存储方式，上传博客时插入的图片路径就找不到了，需要手动再把图片上传上去，并且修改路径，很麻烦</summary>
    
    
    
    <category term="实用分享" scheme="https://blog.imzjw.cn/categories/%E5%AE%9E%E7%94%A8%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="图床" scheme="https://blog.imzjw.cn/tags/%E5%9B%BE%E5%BA%8A/"/>
    
  </entry>
  
  <entry>
    <title>MyBatis-Plus代码生成器</title>
    <link href="https://blog.imzjw.cn/posts/bd1/"/>
    <id>https://blog.imzjw.cn/posts/bd1/</id>
    <published>2020-05-19T03:10:46.000Z</published>
    <updated>2020-05-19T03:10:46.000Z</updated>
    
    <content type="html"><![CDATA[<div class="note info flat"><p>MybatisPlus 给我们提供了更加强大的代码生成器</p></div><p>代码生成器，根据数据库生成实体类，<code>dao</code>，<code>service</code>，<code>controller </code>层代码以及 <code>mapper</code> 映射文件，简化开发</p><h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><ul><li><p>在 pom 文件中添加如下依赖</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 版本 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">mybatisplus.version</span>&gt;</span>3.2.0<span class="tag">&lt;/<span class="name">mybatisplus.version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">lang3.version</span>&gt;</span>3.9<span class="tag">&lt;/<span class="name">lang3.version</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--  mybatisplus代码生成器依赖  --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.baomidou<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-plus-generator<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;mybatisplus.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.velocity<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>velocity-engine-core<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.freemarker<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>freemarker<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.3.29<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.ibeetl<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>beetl<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.0.11.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 加入 slf4j ,查看日志输出信息 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.slf4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>slf4j-api<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.7.7<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.slf4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>slf4j-log4j12<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.7.7<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>复制如下代码到项目任意位置</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.enums.IdType;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.exceptions.MybatisPlusException;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.AutoGenerator;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.config.DataSourceConfig;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.config.GlobalConfig;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.config.PackageConfig;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.config.StrategyConfig;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.config.rules.DbType;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.lang3.StringUtils;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Scanner;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> GarveyZhong</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span> 2020/5/19 11:25</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestMp3</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 作者名称</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">AUTHOR</span> <span class="operator">=</span> <span class="string">&quot;GarveyZhong&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 生成的位置</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">OUTPUT_DIR</span> <span class="operator">=</span> <span class="string">&quot;D:/代码生成/&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 驱动，注意版本</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">DRIVER</span> <span class="operator">=</span> <span class="string">&quot;com.mysql.cj.jdbc.Driver&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 连接路径,注意修改数据库名称</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">URL</span> <span class="operator">=</span> <span class="string">&quot;jdbc:mysql://localhost:3306/mp?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 数据库用户名</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">USERNAME</span> <span class="operator">=</span> <span class="string">&quot;root&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 数据库密码</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">PASSWORD</span> <span class="operator">=</span> <span class="string">&quot;root&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 数据库表的前缀，如t_user</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">TABLE_PREFIX</span> <span class="operator">=</span> <span class="string">&quot;t_&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 顶级包结构</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">PARENT_PACKAGE</span> <span class="operator">=</span> <span class="string">&quot;com.zjw&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 数据访问层包名称</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">DAO</span> <span class="operator">=</span> <span class="string">&quot;dao&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 业务逻辑层包名称</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">SERVICE</span> <span class="operator">=</span> <span class="string">&quot;service&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 实体层包名称</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">ENTITY</span> <span class="operator">=</span> <span class="string">&quot;entity&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 控制器层包名称</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">CONTROLLER</span> <span class="operator">=</span> <span class="string">&quot;controller&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * mapper映射文件包名称</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">MAPPER_XML</span> <span class="operator">=</span> <span class="string">&quot;mapper&quot;</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 模块名</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">MODULE_NAME</span> <span class="operator">=</span> <span class="string">&quot;sys&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 读取控制台内容</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">scanner</span><span class="params">(String tip)</span> &#123;</span><br><span class="line">        <span class="type">Scanner</span> <span class="variable">scanner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Scanner</span>(System.in);</span><br><span class="line">        <span class="type">StringBuilder</span> <span class="variable">help</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StringBuilder</span>();</span><br><span class="line">        help.append(<span class="string">&quot;请输入&quot;</span> + tip + <span class="string">&quot;：&quot;</span>);</span><br><span class="line">        System.out.println(help.toString());</span><br><span class="line">        <span class="keyword">if</span> (scanner.hasNext()) &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">ipt</span> <span class="operator">=</span> scanner.next();</span><br><span class="line">            <span class="keyword">if</span> (StringUtils.isNotEmpty(ipt)) &#123;</span><br><span class="line">                <span class="keyword">return</span> ipt;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">MybatisPlusException</span>(<span class="string">&quot;请输入正确的&quot;</span> + tip + <span class="string">&quot;！&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 1. 全局配置</span></span><br><span class="line">        <span class="type">GlobalConfig</span> <span class="variable">config</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">GlobalConfig</span>();</span><br><span class="line">        config.setAuthor(AUTHOR) <span class="comment">// 作者</span></span><br><span class="line">                <span class="comment">// 生成路径</span></span><br><span class="line">                .setOutputDir(OUTPUT_DIR)</span><br><span class="line">                <span class="comment">// 文件覆盖</span></span><br><span class="line">                .setFileOverride(<span class="literal">true</span>)</span><br><span class="line">                <span class="comment">// 主键策略</span></span><br><span class="line">                .setIdType(IdType.AUTO)</span><br><span class="line">                <span class="comment">// 设置生成的service接口的名字的首字母是否为I，加%s则不生成I</span></span><br><span class="line">                .setServiceName(<span class="string">&quot;%sService&quot;</span>)</span><br><span class="line">                <span class="comment">// 映射文件中是否生成ResultMap配置</span></span><br><span class="line">                .setBaseResultMap(<span class="literal">true</span>)</span><br><span class="line">                <span class="comment">// 生成通用sql字段</span></span><br><span class="line">                .setBaseColumnList(<span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//2. 数据源配置</span></span><br><span class="line">        <span class="type">DataSourceConfig</span> <span class="variable">dsConfig</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DataSourceConfig</span>();</span><br><span class="line">        <span class="comment">// 设置数据库类型</span></span><br><span class="line">        dsConfig.setDbType(DbType.MYSQL)</span><br><span class="line">                <span class="comment">//设置驱动</span></span><br><span class="line">                .setDriverName(DRIVER)</span><br><span class="line">                <span class="comment">//设置连接路径</span></span><br><span class="line">                .setUrl(URL)</span><br><span class="line">                <span class="comment">//设置用户名</span></span><br><span class="line">                .setUsername(USERNAME)</span><br><span class="line">                <span class="comment">//设置密码</span></span><br><span class="line">                .setPassword(PASSWORD);</span><br><span class="line">        <span class="comment">//4. 包名策略配置</span></span><br><span class="line">        <span class="type">PackageConfig</span> <span class="variable">pkConfig</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">PackageConfig</span>();</span><br><span class="line">        <span class="comment">// 顶级包结构</span></span><br><span class="line">        pkConfig.setParent(PARENT_PACKAGE)</span><br><span class="line">                <span class="comment">//数据访问层</span></span><br><span class="line">                .setMapper(DAO)</span><br><span class="line">                <span class="comment">//业务逻辑层</span></span><br><span class="line">                .setService(SERVICE)</span><br><span class="line">                <span class="comment">//控制器</span></span><br><span class="line">                .setController(CONTROLLER)</span><br><span class="line">                <span class="comment">//实体类</span></span><br><span class="line">                .setEntity(ENTITY)</span><br><span class="line">                <span class="comment">//mapper映射文件</span></span><br><span class="line">                .setXml(MAPPER_XML)</span><br><span class="line">                <span class="comment">//模块名;</span></span><br><span class="line">                .setModuleName(scanner(<span class="string">&quot;模块名&quot;</span>));</span><br><span class="line"></span><br><span class="line">        <span class="comment">//3. 策略配置</span></span><br><span class="line">        <span class="type">StrategyConfig</span> <span class="variable">stConfig</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StrategyConfig</span>();</span><br><span class="line">        <span class="comment">//全局大写命名</span></span><br><span class="line">        stConfig.setCapitalMode(<span class="literal">true</span>)</span><br><span class="line">                <span class="comment">// 数据库表映射到实体的命名策略</span></span><br><span class="line">                .setNaming(NamingStrategy.underline_to_camel)</span><br><span class="line">                .setColumnNaming(NamingStrategy.underline_to_camel)</span><br><span class="line">                <span class="comment">//.setTablePrefix(tablePrefix) //表前缀</span></span><br><span class="line">                .setInclude(scanner(<span class="string">&quot;请输入表名(多个以英文逗号隔开):&quot;</span>).split(<span class="string">&quot;,&quot;</span>))</span><br><span class="line">                .setTablePrefix(pkConfig.getModuleName() + <span class="string">&quot;_&quot;</span>)</span><br><span class="line">                <span class="comment">//.setInclude(tables) // 生成的表</span></span><br><span class="line">                .setControllerMappingHyphenStyle(<span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//5. 整合配置</span></span><br><span class="line">        <span class="type">AutoGenerator</span> <span class="variable">ag</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AutoGenerator</span>();</span><br><span class="line">        ag.setGlobalConfig(config)</span><br><span class="line">                .setDataSource(dsConfig)</span><br><span class="line">                .setStrategy(stConfig)</span><br><span class="line">                .setPackageInfo(pkConfig);</span><br><span class="line">        <span class="comment">//6. 执行</span></span><br><span class="line">        ag.execute();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>运行 main 方法，输入相关信息，生成代码</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/bd1/20200526160207.webp" alt="img"></p></li></ul><p>至此代码就生成成功了</p>]]></content>
    
    
    <summary type="html">MybatisPlus 给我们提供了更加强大的代码生成器，代码生成器，根据数据库生成实体类，dao，service，controller 层代码以及 mapper 映射文件，简化开发</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="MyBatis-Plus" scheme="https://blog.imzjw.cn/tags/MyBatis-Plus/"/>
    
  </entry>
  
  <entry>
    <title>valine 修改邮件样式</title>
    <link href="https://blog.imzjw.cn/posts/d110/"/>
    <id>https://blog.imzjw.cn/posts/d110/</id>
    <published>2020-04-25T14:37:20.000Z</published>
    <updated>2020-04-25T14:37:20.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><div class="note info flat"><p>Valine 众所周知是一款快速、简洁且高效的无后端评论系统。</p></div><h2 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h2><ul><li>快速</li><li>安全</li><li>Emoji 😉</li><li>无后端实现</li><li>MarkDown 全语法支持</li><li>轻量易用</li></ul><div class="note info flat"><p>想了解更多的还是去 Valine 的<a href="https://valine.js.org/">官网</a></p></div><p>valine 的默认邮件样式是真的😅😅😅….后来发现了 <a href="https://bili33.top/">@GamerNoTitle</a> 这位大佬的邮件模板很好看，索性就用他的模板，废话不多讲，先来看一下<code>效果图</code></p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d110/6fefb35ebe5f1.webp" width="70%" alt="img"><h3 id="实现步骤"><a href="#实现步骤" class="headerlink" title="实现步骤"></a>实现步骤</h3><ol><li><p>登录 valine 后台 <a href="https://console.leancloud.app/">https://console.leancloud.app</a></p></li><li><p>云引擎 —&gt; 设置</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d110/20200526151159.webp" height="400" alt="img"></li><li><p>找到自定义环境变量并添加新的<code>两个</code>变量</p><ul><li>MAIL_TEMPLATE 和 MAIL_TEMPLATE_ADMIN</li></ul></li><li><p>MAIL_TEMPLATE 所对应的变量值</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;border-radius: 10px 10px 10px 10px;font-size:13px;    color: #555555;width: 666px;font-family:&#x27;Century Gothic&#x27;,&#x27;Trebuchet MS&#x27;,&#x27;Hiragino Sans GB&#x27;,微软雅黑,&#x27;Microsoft Yahei&#x27;,Tahoma,Helvetica,Arial,&#x27;SimSun&#x27;,sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">p</span> <span class="attr">style</span>=<span class="string">&quot;font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;&quot;</span>&gt;</span>您在<span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration:none;color: #ffffff;&quot;</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;SITE_URL&#125;&quot;</span>&gt;</span> $&#123;SITE_NAME&#125;<span class="tag">&lt;/<span class="name">a</span>&gt;</span>上的留言有新回复啦！<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;margin:40px auto;width:90%&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">p</span>&gt;</span>$&#123;PARENT_NICK&#125; 同学，您曾在文章上发表评论：<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;&quot;</span>&gt;</span>$&#123;PARENT_COMMENT&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">p</span>&gt;</span>$&#123;NICK&#125; 给您的回复如下：<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;&quot;</span>&gt;</span>$&#123;COMMENT&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">p</span>&gt;</span>您可以点击<span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration:none; color:#12addb&quot;</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;POST_URL&#125;#comments&quot;</span>&gt;</span>查看回复的完整內容<span class="tag">&lt;/<span class="name">a</span>&gt;</span>，欢迎再次光临<span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration:none; color:#12addb&quot;</span>                <span class="attr">href</span>=<span class="string">&quot;$&#123;SITE_URL&#125;&quot;</span>&gt;</span> $&#123;SITE_NAME&#125;<span class="tag">&lt;/<span class="name">a</span>&gt;</span>。<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-tag">a</span><span class="selector-pseudo">:link</span>&#123;<span class="attribute">text-decoration</span>:none&#125;<span class="selector-tag">a</span><span class="selector-pseudo">:visited</span>&#123;<span class="attribute">text-decoration</span>:none&#125;<span class="selector-tag">a</span><span class="selector-pseudo">:hover</span>&#123;<span class="attribute">text-decoration</span>:none&#125;<span class="selector-tag">a</span><span class="selector-pseudo">:active</span>&#123;<span class="attribute">text-decoration</span>:none&#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>MAIL_TEMPLATE_ADMIN 所对应的变量值</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;border-radius: 10px 10px 10px 10px;font-size:13px;    color: #555555;width: 666px;font-family:&#x27;Century Gothic&#x27;,&#x27;Trebuchet MS&#x27;,&#x27;Hiragino Sans GB&#x27;,微软雅黑,&#x27;Microsoft Yahei&#x27;,Tahoma,Helvetica,Arial,&#x27;SimSun&#x27;,sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">p</span> <span class="attr">style</span>=<span class="string">&quot;font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;&quot;</span>&gt;</span>您的<span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration:none;color: #ffffff;&quot;</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;SITE_URL&#125;&quot;</span>&gt;</span> $&#123;SITE_NAME&#125;<span class="tag">&lt;/<span class="name">a</span>&gt;</span>上有新的留言：<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;margin:40px auto;width:90%&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">p</span>&gt;</span>$&#123;NICK&#125; 给您的留言如下：<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;&quot;</span>&gt;</span>$&#123;COMMENT&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">p</span>&gt;</span>您可以点击<span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration:none; color:#12addb&quot;</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;POST_URL&#125;#comments&quot;</span>&gt;</span>查看回复的完整內容<span class="tag">&lt;/<span class="name">a</span>&gt;</span>，欢迎再次光临<span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration:none; color:#12addb&quot;</span>                <span class="attr">href</span>=<span class="string">&quot;$&#123;SITE_URL&#125;&quot;</span>&gt;</span> $&#123;SITE_NAME&#125;<span class="tag">&lt;/<span class="name">a</span>&gt;</span>。<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-tag">a</span><span class="selector-pseudo">:link</span>&#123;<span class="attribute">text-decoration</span>:none&#125;<span class="selector-tag">a</span><span class="selector-pseudo">:visited</span>&#123;<span class="attribute">text-decoration</span>:none&#125;<span class="selector-tag">a</span><span class="selector-pseudo">:hover</span>&#123;<span class="attribute">text-decoration</span>:none&#125;<span class="selector-tag">a</span><span class="selector-pseudo">:active</span>&#123;<span class="attribute">text-decoration</span>:none&#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d110/valine.webp" alt="img"></p></li><li><p>最后保存重启云引擎大功告成！</p></li></ol>]]></content>
    
    
    <summary type="html">Valine 众所周知是一款快速、简洁且高效的无后端评论系统。特性：快速、安全、Emoji 😉、无后端实现、MarkDown 全语法支持、轻量易用，想了解更多的还是去 Valine 的官网</summary>
    
    
    
    <category term="Hexo" scheme="https://blog.imzjw.cn/categories/Hexo/"/>
    
    
    <category term="Valine" scheme="https://blog.imzjw.cn/tags/Valine/"/>
    
  </entry>
  
  <entry>
    <title>那些有趣的注释</title>
    <link href="https://blog.imzjw.cn/posts/8786/"/>
    <id>https://blog.imzjw.cn/posts/8786/</id>
    <published>2020-04-05T04:06:17.000Z</published>
    <updated>2020-04-05T04:06:17.000Z</updated>
    
    <content type="html"><![CDATA[<p><strong>闲来无事收集了一些有趣的注释，各式各样的都有，喜欢哪一款拿走不谢</strong></p><h2 id="第一款：佛祖保佑，永无BUG"><a href="#第一款：佛祖保佑，永无BUG" class="headerlink" title="第一款：佛祖保佑，永无BUG"></a>第一款：佛祖保佑，永无BUG</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//                            _ooOoo_    </span></span><br><span class="line"><span class="comment">//                           o8888888o    </span></span><br><span class="line"><span class="comment">//                           88&quot; . &quot;88    </span></span><br><span class="line"><span class="comment">//                           (| -_- |)    </span></span><br><span class="line"><span class="comment">//                            O\ = /O    </span></span><br><span class="line"><span class="comment">//                        ____/`---&#x27;\____    </span></span><br><span class="line"><span class="comment">//                      .   &#x27; \\| |// `.    </span></span><br><span class="line"><span class="comment">//                       / \\||| : |||// \    </span></span><br><span class="line"><span class="comment">//                     / _||||| -:- |||||- \    </span></span><br><span class="line"><span class="comment">//                       | | \\\ - /// | |    </span></span><br><span class="line"><span class="comment">//                     | \_| &#x27;&#x27;\---/&#x27;&#x27; | |    </span></span><br><span class="line"><span class="comment">//                      \ .-\__ `-` ___/-. /    </span></span><br><span class="line"><span class="comment">//                   ___`. .&#x27; /--.--\ `. . __    </span></span><br><span class="line"><span class="comment">//                .&quot;&quot; &#x27;&lt; `.___\_&lt;|&gt;_/___.&#x27; &gt;&#x27;&quot;&quot;.    </span></span><br><span class="line"><span class="comment">//               | | : `- \`.;`\ _ /`;.`/ - ` : | |    </span></span><br><span class="line"><span class="comment">//                 \ \ `-. \_ __\ /__ _/ .-` / /    </span></span><br><span class="line"><span class="comment">//         ======`-.____`-.___\_____/___.-`____.-&#x27;======    </span></span><br><span class="line"><span class="comment">//                            `=---=&#x27;    </span></span><br><span class="line"><span class="comment">//    </span></span><br><span class="line"><span class="comment">//         .............................................    </span></span><br><span class="line"><span class="comment">//                  佛祖保佑             永无BUG</span></span><br></pre></td></tr></table></figure><h2 id="第二款：神兽护体，永无BUG"><a href="#第二款：神兽护体，永无BUG" class="headerlink" title="第二款：神兽护体，永无BUG"></a>第二款：神兽护体，永无BUG</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ┏┓　　　┏┓</span></span><br><span class="line"><span class="comment">// ┏┛┻━━━┛┻┓</span></span><br><span class="line"><span class="comment">// ┃　　　　　　　┃ 　</span></span><br><span class="line"><span class="comment">// ┃　　　━　　　┃</span></span><br><span class="line"><span class="comment">// ┃　┳┛　┗┳　┃</span></span><br><span class="line"><span class="comment">// ┃　　　　　　　┃</span></span><br><span class="line"><span class="comment">// ┃　　　┻　　　┃</span></span><br><span class="line"><span class="comment">// ┃　　　　　　　┃</span></span><br><span class="line"><span class="comment">// ┗━┓　　　┏━┛</span></span><br><span class="line"><span class="comment">// ┃　　　┃ Code is far away from bug with the animal protecting　　　　　　　　</span></span><br><span class="line"><span class="comment">// ┃　　　┃ 神兽保护，永无BUG！</span></span><br><span class="line"><span class="comment">// ┃　　　┗━━━┓</span></span><br><span class="line"><span class="comment">// ┃　　　　　　　┣┓</span></span><br><span class="line"><span class="comment">// ┃　　　　　　　┏┛</span></span><br><span class="line"><span class="comment">// ┗┓┓┏━┳┓┏┛</span></span><br><span class="line"><span class="comment">// ┃┫┫　┃┫┫</span></span><br><span class="line"><span class="comment">// ┗┻┛　┗┻┛</span></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *　　　　　　　　┏┓　　　┏┓+ +</span></span><br><span class="line"><span class="comment"> *　　　　　　　┏┛┻━━━┛┻┓ + +</span></span><br><span class="line"><span class="comment"> *　　　　　　　┃　　　　　　　┃ 　</span></span><br><span class="line"><span class="comment"> *　　　　　　　┃　　　━　　　┃ ++ + + +</span></span><br><span class="line"><span class="comment"> *　　　　　　 ████━████ ┃+</span></span><br><span class="line"><span class="comment"> *　　　　　　　┃　　　　　　　┃ +</span></span><br><span class="line"><span class="comment"> *　　　　　　　┃　　　┻　　　┃</span></span><br><span class="line"><span class="comment"> *　　　　　　　┃　　　　　　　┃ + +</span></span><br><span class="line"><span class="comment"> *　　　　　　　┗━┓　　　┏━┛</span></span><br><span class="line"><span class="comment"> *　　　　　　　　　┃　　　┃　　　　　　　　　　　</span></span><br><span class="line"><span class="comment"> *　　　　　　　　　┃　　　┃ + + + +</span></span><br><span class="line"><span class="comment"> *　　　　　　　　　┃　　　┃　Code is far away from bug with the animal protecting　　　　　　　</span></span><br><span class="line"><span class="comment"> *　　　　　　　　　┃　　　┃ + 神兽保佑,永无bug　　</span></span><br><span class="line"><span class="comment"> *　　　　　　　　　┃　　　┃</span></span><br><span class="line"><span class="comment"> *　　　　　　　　　┃　　　┃　　+　　　　　　　　　</span></span><br><span class="line"><span class="comment"> *　　　　　　　　　┃　 　　┗━━━┓ + +</span></span><br><span class="line"><span class="comment"> *　　　　　　　　　┃ 　　　　　　　┣┓</span></span><br><span class="line"><span class="comment"> *　　　　　　　　　┃ 　　　　　　　┏┛</span></span><br><span class="line"><span class="comment"> *　　　　　　　　　┗┓┓┏━┳┓┏┛ + + + +</span></span><br><span class="line"><span class="comment"> *　　　　　　　　　　┃┫┫　┃┫┫</span></span><br><span class="line"><span class="comment"> *　　　　　　　　　　┗┻┛　┗┻┛+ + + +</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure><h2 id="第三款：来首程序员打油诗，笑"><a href="#第三款：来首程序员打油诗，笑" class="headerlink" title="第三款：来首程序员打油诗，笑"></a>第三款：来首程序员打油诗，笑</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *                      江城子 . 程序员之歌</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> *                  十年生死两茫茫，写程序，到天亮。</span></span><br><span class="line"><span class="comment"> *                      千行代码，Bug何处藏。</span></span><br><span class="line"><span class="comment"> *                  纵使上线又怎样，朝令改，夕断肠。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> *                  领导每天新想法，天天改，日日忙。</span></span><br><span class="line"><span class="comment"> *                      相顾无言，惟有泪千行。</span></span><br><span class="line"><span class="comment"> *                  每晚灯火阑珊处，夜难寐，加班狂。</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *          写字楼里写字间，写字间里程序员；</span></span><br><span class="line"><span class="comment"> *          程序人员写程序，又拿程序换酒钱。</span></span><br><span class="line"><span class="comment"> *          酒醒只在网上坐，酒醉还来网下眠；</span></span><br><span class="line"><span class="comment"> *          酒醉酒醒日复日，网上网下年复年。</span></span><br><span class="line"><span class="comment"> *          但愿老死电脑间，不愿鞠躬老板前；</span></span><br><span class="line"><span class="comment"> *          奔驰宝马贵者趣，公交自行程序员。</span></span><br><span class="line"><span class="comment"> *          别人笑我忒疯癫，我笑自己命太贱；</span></span><br><span class="line"><span class="comment"> *          不见满街漂亮妹，哪个归得程序员？</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure><h2 id="第四款：无尽诱惑"><a href="#第四款：无尽诱惑" class="headerlink" title="第四款：无尽诱惑"></a>第四款：无尽诱惑</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">//                       .::::.</span></span><br><span class="line"><span class="comment">//                     .::::::::.</span></span><br><span class="line"><span class="comment">//                    :::::::::::</span></span><br><span class="line"><span class="comment">//                 ..:::::::::::&#x27;</span></span><br><span class="line"><span class="comment">//              &#x27;::::::::::::&#x27;</span></span><br><span class="line"><span class="comment">//                .::::::::::</span></span><br><span class="line"><span class="comment">//           &#x27;::::::::::::::..</span></span><br><span class="line"><span class="comment">//                ..::::::::::::.</span></span><br><span class="line"><span class="comment">//              ``::::::::::::::::</span></span><br><span class="line"><span class="comment">//               ::::``:::::::::&#x27;        .:::.</span></span><br><span class="line"><span class="comment">//              ::::&#x27;   &#x27;:::::&#x27;       .::::::::.</span></span><br><span class="line"><span class="comment">//            .::::&#x27;      ::::     .:::::::&#x27;::::.</span></span><br><span class="line"><span class="comment">//           .:::&#x27;       :::::  .:::::::::&#x27; &#x27;:::::.</span></span><br><span class="line"><span class="comment">//          .::&#x27;        :::::.:::::::::&#x27;      &#x27;:::::.</span></span><br><span class="line"><span class="comment">//         .::&#x27;         ::::::::::::::&#x27;         ``::::.</span></span><br><span class="line"><span class="comment">//     ...:::           ::::::::::::&#x27;              ``::.</span></span><br><span class="line"><span class="comment">//    ```` &#x27;:.          &#x27;:::::::::&#x27;                  ::::..</span></span><br><span class="line"><span class="comment">//                       &#x27;.:::::&#x27;                    &#x27;:&#x27;````..</span></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *           _.._        ,------------.</span></span><br><span class="line"><span class="comment"> *        ,&#x27;      `.    ( We want you! )</span></span><br><span class="line"><span class="comment"> *       /  __) __` \    `-,----------&#x27;</span></span><br><span class="line"><span class="comment"> *      (  (`-`(-&#x27;)  ) _.-&#x27;</span></span><br><span class="line"><span class="comment"> *      /)  \  = /  (</span></span><br><span class="line"><span class="comment"> *     /&#x27;    |--&#x27; .  \</span></span><br><span class="line"><span class="comment"> *    (  ,---|  `-.)__`</span></span><br><span class="line"><span class="comment"> *     )(  `-.,--&#x27;   _`-.</span></span><br><span class="line"><span class="comment"> *    &#x27;/,&#x27;          (  Uu&quot;,</span></span><br><span class="line"><span class="comment"> *     (_       ,    `/,-&#x27; )</span></span><br><span class="line"><span class="comment"> *     `.__,  : `-&#x27;/  /`--&#x27;</span></span><br><span class="line"><span class="comment"> *       |     `--&#x27;  |</span></span><br><span class="line"><span class="comment"> *       `   `-._   /</span></span><br><span class="line"><span class="comment"> *        \        (</span></span><br><span class="line"><span class="comment"> *        /\ .      \. </span></span><br><span class="line"><span class="comment"> *       / |` \     ,-\</span></span><br><span class="line"><span class="comment"> *      /  \| .)   /   \</span></span><br><span class="line"><span class="comment"> *     ( ,&#x27;|\    ,&#x27;     :</span></span><br><span class="line"><span class="comment"> *     | \,`.`--&quot;/      &#125;</span></span><br><span class="line"><span class="comment"> *     `,&#x27;    \  |,&#x27;    /</span></span><br><span class="line"><span class="comment"> *    / &quot;-._   `-/      |</span></span><br><span class="line"><span class="comment"> *    &quot;-.   &quot;-.,&#x27;|     ;</span></span><br><span class="line"><span class="comment"> *   /        _/[&quot;---&#x27;&quot;&quot;]</span></span><br><span class="line"><span class="comment"> *  :        /  |&quot;-     &#x27;</span></span><br><span class="line"><span class="comment"> *  &#x27;           |      /</span></span><br><span class="line"><span class="comment"> *              `      |</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure><h2 id="第五款：单身狗专用"><a href="#第五款：单身狗专用" class="headerlink" title="第五款：单身狗专用"></a>第五款：单身狗专用</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">&lt;!--</span><br><span class="line">                       ::</span><br><span class="line">                      :;J7, :,                        ::;<span class="number">7</span>:</span><br><span class="line">                      ,ivYi, ,                       ;LLLFS:</span><br><span class="line">                      :iv7Yi                       :7ri;j5PL</span><br><span class="line">                     ,:ivYLvr                    ,ivrrirrY2X,</span><br><span class="line">                     :;r<span class="meta">@Wwz</span>.7r:                :ivu<span class="meta">@kexianli</span>.</span><br><span class="line">                    :iL7::,:::iiirii:ii;::::,,irvF7rvvLujL7ur</span><br><span class="line">                   ri::,:,::i:iiiiiii:i:irrv177JX7rYXqZEkvv17</span><br><span class="line">                ;i:, , ::::iirrririi:i:::iiir2XXvii;L8OGJr71i</span><br><span class="line">              :,, ,,:   ,::ir<span class="meta">@mingyi</span>.irii:i:::j1jri7ZBOS7ivv,</span><br><span class="line">                 ,::,    ::rv77iiiriii:iii:i::,rvLq<span class="meta">@huhao</span>.Li</span><br><span class="line">             ,,      ,, ,:ir7ir::,:::i;ir:::i:i::rSGGYri712:</span><br><span class="line">           :::  ,v7r:: ::rrv77:, ,, ,:i7rrii:::::, ir7ri7Lri</span><br><span class="line">          ,     2OBBOi,iiir;r::        ,irriiii::,, ,iv7Luur:</span><br><span class="line">        ,,     i78MBBi,:,:::,:,  :7FSL: ,iriii:::i::,,:rLqXv::</span><br><span class="line">        :      iuMMP: :,:::,:ii;2GY7OBB0viiii:i:iii:i:::iJqL;::</span><br><span class="line">       ,     ::::i   ,,,,, ::LuBBu BBBBBErii:i:i:i:i:i:i:r77ii</span><br><span class="line">      ,       :       , ,,:::rruBZ1MBBqi, :,,,:::,::::::iiriri:</span><br><span class="line">     ,               ,,,,::::i:  <span class="meta">@arqiao</span>.       ,:,, ,:::ii;i7:</span><br><span class="line">    :,       rjujLYLi   ,,:::::,:::::::::,,   ,:i,:,,,,,::i:iii</span><br><span class="line">    ::      BBBBBBBBB0,    ,,::: , ,:::::: ,      ,,,, ,,:::::::</span><br><span class="line">    i,  ,  ,8BMMBBBBBBi     ,,:,,     ,,, , ,   , , , :,::ii::i::</span><br><span class="line">    :      iZMOMOMBBM2::::::::::,,,,     ,,,,,,:,,,::::i:irr:i:::,</span><br><span class="line">    i   ,,:;u0MBMOG1L:::i::::::  ,,,::,   ,,, ::::::i:i:iirii:i:i:</span><br><span class="line">    :    ,iuUuuXUkFu7i:iii:i:::, :,:,: ::::::::i:i:::::iirr7iiri::</span><br><span class="line">    :     :rk<span class="meta">@Yizero</span>.i:::::, ,:ii:::::::i:::::i::,::::iirrriiiri::,</span><br><span class="line">     :      5BMBBBBBBSr:,::rv2kuii:::iii::,:i:,, , ,,:,:i<span class="meta">@petermu</span>.,</span><br><span class="line">          , :r50EZ8MBBBBGOBBBZP7::::i::,:::::,: :,:,::i;rrririiii::</span><br><span class="line">              :jujYY7LS0ujJL7r::,::i::,::::::::::::::iirirrrrrrr:ii:</span><br><span class="line">           ,:  :<span class="meta">@kevensun</span>.:,:,,,::::i:i:::::,,::::::iir;ii;7v77;ii;i,</span><br><span class="line">           ,,,     ,,:,::::::i:iiiii:i::::,, ::::iiiir<span class="meta">@xingjief</span>.r;<span class="number">7</span>:i,</span><br><span class="line">        , , ,,,:,,::::::::iiiiiiiiii:,:,:::::::::iiir;ri7vL77rrirri::</span><br><span class="line">         :,, , ::::::::i:::i:::i:i::,,,,,:,::i:i:::iir;<span class="meta">@Secbone</span>.ii:::</span><br><span class="line"></span><br><span class="line">--&gt;</span><br></pre></td></tr></table></figure><h2 id="第六款：骷髅头"><a href="#第六款：骷髅头" class="headerlink" title="第六款：骷髅头"></a>第六款：骷髅头</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> **************************************************************</span></span><br><span class="line"><span class="comment"> *                                                            *</span></span><br><span class="line"><span class="comment"> *   .=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-.       *</span></span><br><span class="line"><span class="comment"> *    |                     ______                     |      *</span></span><br><span class="line"><span class="comment"> *    |                  .-&quot;      &quot;-.                  |      *</span></span><br><span class="line"><span class="comment"> *    |                 /            \                 |      *</span></span><br><span class="line"><span class="comment"> *    |     _          |              |          _     |      *</span></span><br><span class="line"><span class="comment"> *    |    ( \         |,  .-.  .-.  ,|         / )    |      *</span></span><br><span class="line"><span class="comment"> *    |     &gt; &quot;=._     | )(__/  \__)( |     _.=&quot; &lt;     |      *</span></span><br><span class="line"><span class="comment"> *    |    (_/&quot;=._&quot;=._ |/     /\     \| _.=&quot;_.=&quot;\_)    |      *</span></span><br><span class="line"><span class="comment"> *    |           &quot;=._&quot;(_     ^^     _)&quot;_.=&quot;           |      *</span></span><br><span class="line"><span class="comment"> *    |               &quot;=\__|IIIIII|__/=&quot;               |      *</span></span><br><span class="line"><span class="comment"> *    |              _.=&quot;| \IIIIII/ |&quot;=._              |      *</span></span><br><span class="line"><span class="comment"> *    |    _     _.=&quot;_.=&quot;\          /&quot;=._&quot;=._     _    |      *</span></span><br><span class="line"><span class="comment"> *    |   ( \_.=&quot;_.=&quot;     `--------`     &quot;=._&quot;=._/ )   |      *</span></span><br><span class="line"><span class="comment"> *    |    &gt; _.=&quot;                            &quot;=._ &lt;    |      *</span></span><br><span class="line"><span class="comment"> *    |   (_/                                    \_)   |      *</span></span><br><span class="line"><span class="comment"> *    |                                                |      *</span></span><br><span class="line"><span class="comment"> *    &#x27;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=&#x27;      *</span></span><br><span class="line"><span class="comment"> *                                                            *</span></span><br><span class="line"><span class="comment"> *           LASCIATE OGNI SPERANZA, VOI CH&#x27;ENTRATE           *</span></span><br><span class="line"><span class="comment"> **************************************************************</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure><h2 id="第七款：标准键盘"><a href="#第七款：标准键盘" class="headerlink" title="第七款：标准键盘"></a>第七款：标准键盘</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * ┌───┐   ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ ┌───┬───┬───┐</span></span><br><span class="line"><span class="comment"> * │Esc│   │ F1│ F2│ F3│ F4│ │ F5│ F6│ F7│ F8│ │ F9│F10│F11│F12│ │P/S│S L│P/B│  ┌┐    ┌┐    ┌┐</span></span><br><span class="line"><span class="comment"> * └───┘   └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┴───┘ └───┴───┴───┘  └┘    └┘    └┘</span></span><br><span class="line"><span class="comment"> * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ ┌───┬───┬───┐ ┌───┬───┬───┬───┐</span></span><br><span class="line"><span class="comment"> * │~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│&amp; 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │N L│ / │ * │ - │</span></span><br><span class="line"><span class="comment"> * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ ├───┼───┼───┤ ├───┼───┼───┼───┤</span></span><br><span class="line"><span class="comment"> * │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │&#123; [│&#125; ]│ | \ │ │Del│End│PDn│ │ 7 │ 8 │ 9 │   │</span></span><br><span class="line"><span class="comment"> * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ └───┴───┴───┘ ├───┼───┼───┤ + │</span></span><br><span class="line"><span class="comment"> * │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │: ;│&quot; &#x27;│ Enter  │               │ 4 │ 5 │ 6 │   │</span></span><br><span class="line"><span class="comment"> * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤     ┌───┐     ├───┼───┼───┼───┤</span></span><br><span class="line"><span class="comment"> * │ Shift  │ Z │ X │ C │ V │ B │ N │ M │&lt; ,│&gt; .│? /│  Shift   │     │ ↑ │     │ 1 │ 2 │ 3 │   │</span></span><br><span class="line"><span class="comment"> * ├─────┬──┴─┬─┴──┬┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ ┌───┼───┼───┐ ├───┴───┼───┤ E││</span></span><br><span class="line"><span class="comment"> * │ Ctrl│    │Alt │         Space         │ Alt│    │    │Ctrl│ │ ← │ ↓ │ → │ │   0   │ . │←─┘│</span></span><br><span class="line"><span class="comment"> * └─────┴────┴────┴───────────────────────┴────┴────┴────┴────┘ └───┴───┴───┘ └───────┴───┴───┘</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure><h2 id="第八款：顶"><a href="#第八款：顶" class="headerlink" title="第八款：顶"></a>第八款：顶</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 頂頂頂頂頂頂頂頂頂　頂頂頂頂頂頂頂頂頂</span></span><br><span class="line"><span class="comment"> * 頂頂頂頂頂頂頂　　　　　頂頂　　　　　</span></span><br><span class="line"><span class="comment"> * 　　　頂頂　　　頂頂頂頂頂頂頂頂頂頂頂</span></span><br><span class="line"><span class="comment"> * 　　　頂頂　　　頂頂頂頂頂頂頂頂頂頂頂</span></span><br><span class="line"><span class="comment"> * 　　　頂頂　　　頂頂　　　　　　　頂頂</span></span><br><span class="line"><span class="comment"> * 　　　頂頂　　　頂頂　　頂頂頂　　頂頂</span></span><br><span class="line"><span class="comment"> * 　　　頂頂　　　頂頂　　頂頂頂　　頂頂</span></span><br><span class="line"><span class="comment"> * 　　　頂頂　　　頂頂　　頂頂頂　　頂頂</span></span><br><span class="line"><span class="comment"> * 　　　頂頂　　　頂頂　　頂頂頂　　頂頂</span></span><br><span class="line"><span class="comment"> * 　　　頂頂　　　　　　　頂頂頂　</span></span><br><span class="line"><span class="comment"> * 　　　頂頂　　　　　　頂頂　頂頂　頂頂</span></span><br><span class="line"><span class="comment"> * 　頂頂頂頂　　　頂頂頂頂頂　頂頂頂頂頂</span></span><br><span class="line"><span class="comment"> * 　頂頂頂頂　　　頂頂頂頂　　　頂頂頂頂</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure><h2 id="还有一些其他有趣搞怪的注释"><a href="#还有一些其他有趣搞怪的注释" class="headerlink" title="还有一些其他有趣搞怪的注释"></a>还有一些其他有趣搞怪的注释</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * _ooOoo_</span></span><br><span class="line"><span class="comment"> * o8888888o</span></span><br><span class="line"><span class="comment"> * 88&quot; . &quot;88</span></span><br><span class="line"><span class="comment"> * (| -_- |)</span></span><br><span class="line"><span class="comment"> *  O\ = /O</span></span><br><span class="line"><span class="comment"> * ___/`---&#x27;\____</span></span><br><span class="line"><span class="comment"> * .   &#x27; \\| |// `.</span></span><br><span class="line"><span class="comment"> * / \\||| : |||// \</span></span><br><span class="line"><span class="comment"> * / _||||| -:- |||||- \</span></span><br><span class="line"><span class="comment"> * | | \\\ - /// | |</span></span><br><span class="line"><span class="comment"> * | \_| &#x27;&#x27;\---/&#x27;&#x27; | |</span></span><br><span class="line"><span class="comment"> * \ .-\__ `-` ___/-. /</span></span><br><span class="line"><span class="comment"> * ___`. .&#x27; /--.--\ `. . __</span></span><br><span class="line"><span class="comment"> * .&quot;&quot; &#x27;&lt; `.___\_&lt;|&gt;_/___.&#x27; &gt;&#x27;&quot;&quot;.</span></span><br><span class="line"><span class="comment"> * | | : `- \`.;`\ _ /`;.`/ - ` : | |</span></span><br><span class="line"><span class="comment"> * \ \ `-. \_ __\ /__ _/ .-` / /</span></span><br><span class="line"><span class="comment"> * ======`-.____`-.___\_____/___.-`____.-&#x27;======</span></span><br><span class="line"><span class="comment"> * `=---=&#x27;</span></span><br><span class="line"><span class="comment"> * .............................................</span></span><br><span class="line"><span class="comment"> * 佛曰：bug泛滥，我已瘫痪！</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *                                         ,s555SB@@&amp;                          </span></span><br><span class="line"><span class="comment"> *                                      :9H####@@@@<span class="doctag">@Xi</span>                        </span></span><br><span class="line"><span class="comment"> *                                     1@@@@@@@@@@@@@@8                       </span></span><br><span class="line"><span class="comment"> *                                   ,8@@@@@@@@<span class="doctag">@B</span>@@@@@@8                      </span></span><br><span class="line"><span class="comment"> *                                  :B@@@<span class="doctag">@X</span>3hi8Bs;B@@@@<span class="doctag">@Ah</span>,                   </span></span><br><span class="line"><span class="comment"> *             ,8i                  r@@<span class="doctag">@B</span>:     1S ,M@@@@@@#8;                 </span></span><br><span class="line"><span class="comment"> *            1AB35.i:               X@@8 .   SGhr ,A@@@@@@@<span class="doctag">@S</span>                </span></span><br><span class="line"><span class="comment"> *            1@h31MX8                18Hhh3i .i3r ,A@@@@@@@@@5               </span></span><br><span class="line"><span class="comment"> *            ;@&amp;i,58r5                 rGSS:     :B@@@@@@@@@<span class="doctag">@A</span>               </span></span><br><span class="line"><span class="comment"> *             1#i  . 9i                 hX.  .: .5@@@@@@@@@@@1               </span></span><br><span class="line"><span class="comment"> *              sG1,  ,G53s.              9#Xi;hS5 3B@@@@@@<span class="doctag">@B</span>1                </span></span><br><span class="line"><span class="comment"> *               .h8h.,A@@<span class="doctag">@MXSs</span>,           #<span class="doctag">@H</span>1:    3ssSSX@1                  </span></span><br><span class="line"><span class="comment"> *               s ,@@@@@@@@@@@<span class="doctag">@Xhi</span>,       r#@<span class="doctag">@X</span>1s9M8    .GA981               </span></span><br><span class="line"><span class="comment"> *               ,. rS8H#@@@@@@@@@@#HG51;.  .h31i;9@r    .8@@@<span class="doctag">@BS</span>;i;          </span></span><br><span class="line"><span class="comment"> *                .19AXXXAB@@@@@@@@@@@@@@#MHXG893hrX#XGGXM@@@@@@@@@<span class="doctag">@MS</span>        </span></span><br><span class="line"><span class="comment"> *                s@<span class="doctag">@MM</span>@@<span class="doctag">@hsX</span>#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&amp;,      </span></span><br><span class="line"><span class="comment"> *              :GB@#3G@<span class="doctag">@Brs</span> ,1GM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@<span class="doctag">@B</span>,     </span></span><br><span class="line"><span class="comment"> *            .hM@@@#@@#MX 51  r;iSGAM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8     </span></span><br><span class="line"><span class="comment"> *          :3B@@@@@@@@@@@&amp;9@h :Gs   .;sSXH@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@:    </span></span><br><span class="line"><span class="comment"> *      s&amp;HA#@@@@@@@@@@@@@<span class="doctag">@M</span>89A;.8S.       ,r3@@@@@@@@@@@@@@@@@@@@@@@@@@<span class="doctag">@r</span>    </span></span><br><span class="line"><span class="comment"> *   ,13B@@@@@@@@@@@@@@@@@@@5 5B3 ;.         ;@@@@@@@@@@@@@@@@@@@@@@@@@@<span class="doctag">@i</span>    </span></span><br><span class="line"><span class="comment"> *  5#@@#&amp;@@@@@@@@@@@@@@@@@@9  .39:          ;@@@@@@@@@@@@@@@@@@@@@@@@@@@;    </span></span><br><span class="line"><span class="comment"> *  9@@<span class="doctag">@X</span>:MM@@@@@@@@@@@@@@@#;    ;31.         H@@@@@@@@@@@@@@@@@@@@@@@@@@:    </span></span><br><span class="line"><span class="comment"> *   SH#<span class="doctag">@B</span>9.rM@@@@@@@@@@@@<span class="doctag">@B</span>       :.         3@@@@@@@@@@@@@@@@@@@@@@@@@@5    </span></span><br><span class="line"><span class="comment"> *     ,:.   9@@@@@@@@@@@#HB5                 .M@@@@@@@@@@@@@@@@@@@@@@@@<span class="doctag">@B</span>    </span></span><br><span class="line"><span class="comment"> *           ,ssirhSM@&amp;1;i19911i,.             s@@@@@@@@@@@@@@@@@@@@@@@@@<span class="doctag">@S</span>   </span></span><br><span class="line"><span class="comment"> *              ,,,rHAri1h1rh&amp;@#353Sh:          8@@@@@@@@@@@@@@@@@@@@@@@@@#:  </span></span><br><span class="line"><span class="comment"> *            .A3hH@#5S553&amp;@@#h   i:i9S          #@@@@@@@@@@@@@@@@@@@@@@@@<span class="doctag">@A</span>. </span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> *   </span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure><p>上面这些都不能满足你的话，想要找更多的 ascii 图在这里</p><p><a href="http://www.asciiworld.com/">http://www.asciiworld.com/</a></p>]]></content>
    
    
    <summary type="html">闲来无事收集了一些有趣的注释, 各式各样的都有, 喜欢哪一款拿走不谢</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Java" scheme="https://blog.imzjw.cn/tags/Java/"/>
    
  </entry>
  
  <entry>
    <title>IDEA 插件 JRebel 破解</title>
    <link href="https://blog.imzjw.cn/posts/d9ab/"/>
    <id>https://blog.imzjw.cn/posts/d9ab/</id>
    <published>2020-04-03T09:02:01.000Z</published>
    <updated>2021-04-15T11:01:22.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>JRebel 插件它使得 JAVA 代码修改后不用重启项目，立即生效。IDEA 原生是不支持热部署的，一般更新了 JAVA 文件后要手动重启 Tomcat 服务器，才能生效，简直是浪费时间浪费生命。</p><p>目前对于 IDEA 热部署最好的解决方案就是安装 JRebel 插件，但是要收费！不过我们可以破解</p><h2 id="安装-JRebel"><a href="#安装-JRebel" class="headerlink" title="安装 JRebel"></a>安装 JRebel</h2><p>IDEA 依次打开 <code>File | Settings | Plugins</code> 搜索 JRebel 进行安装并重启 IDEA</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d9ab/20200526150825.webp" alt="img"></p><h2 id="破解步骤"><a href="#破解步骤" class="headerlink" title="破解步骤"></a>破解步骤</h2><ol><li><p>生成 GUID：<a class="btn-beautify pink" href="https://www.guidgen.com/"   title="在线生成 GUID 地址"><i class="far fa-hand-point-right"></i><span>在线生成 GUID 地址</span></a>  并把 GUID 复制下来</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d9ab/guid.4ojgsdimjc40.webp" alt="guid"></p></li><li><p>在 IDEA 打开 <code>File | Settings | JRebel &amp; XRebel</code> 点击 <code>Activate now</code> 进行激活</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d9ab/activate%20now.3znfz8ozdm80.webp" alt="activate now"></p><p>根据反向代理服务器地址拼接激活地址，例如：<code>https://jrebel.qekang.com/填刚刚生成的 GUID</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d9ab/img.1y2rfqoxkps0.webp" alt="img"></p><p>如果失效刷新 GUID 替换就可以！<code>邮箱</code>可以随便填写！之后勾选服务条款，最后点击 <code>Activate JRebel</code></p></li><li><p>激活成功</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d9ab/image-20210225191015154.3xucxgm4kd40.webp" alt="images"></p></li></ol><div class="note danger flat"><p>注：上面的激活使用了别人的代理地址，如果别人代理地址下线了，你的激活状态会是不可用的一个状态！</p></div><h2 id="JRebel-不自动部署的原因"><a href="#JRebel-不自动部署的原因" class="headerlink" title="JRebel 不自动部署的原因"></a>JRebel 不自动部署的原因</h2><ol><li><p>确保是以 <code>JRebel</code> 方式启动，而非原生 IDEA 启动方式</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d9ab/20200526150914.webp" alt="img"></p></li><li><p>确保对项目进行了热部署的设置，在  <code>View &gt; Tool Windows &gt; JRebel</code> 中打开 JRebel 的视图，勾选上需要启动热部署的项目，一般就会在你的  <code>resources</code> 目录下生成一个 <code>rebel.xml</code> 文件，具体效果如下图</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d9ab/image-20210225191850684.1095miy0cihs.webp" alt="img"></p></li><li><p>打开 <code>File | Settings | Build, Execution, Deployment | Compiler</code> 把  <code>Build project automatically</code>  勾上</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d9ab/20200526150944.webp" alt="img"></li><li><p>按下组合快捷键  <kbd>CTRL</kbd> + <kbd>SHIFT</kbd> + <kbd>ALT</kbd> + <kbd>/</kbd> 点击 Registry…</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d9ab/20200526150956.webp" alt="img"></p><p>找到并勾上如图所示</p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d9ab/20200526151013.webp" alt="img"></li></ol><div class="note danger flat"><p>最后记得点一下 work offline，把  JRebel  设置为 offline 模式 </p></div><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/d9ab/20201108155410.webp" alt="img">]]></content>
    
    
    <summary type="html">JRebel 是一款 JVM 插件，它使得 Java 代码修改后不用重启系统，立即生效。IDEA 原生是不支持热部署的，一般更新了 Java 文件后要手动重启 Tomcat 服务器，才能生效，浪费时间浪费生命</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="IntelliJ IDEA" scheme="https://blog.imzjw.cn/tags/IntelliJ-IDEA/"/>
    
  </entry>
  
  <entry>
    <title>org.apache.ibatis.binding.BindingException原因总结</title>
    <link href="https://blog.imzjw.cn/posts/ede9/"/>
    <id>https://blog.imzjw.cn/posts/ede9/</id>
    <published>2020-03-25T08:41:54.000Z</published>
    <updated>2020-03-25T08:41:54.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>今天遇到 Mybatis 的报错，绞尽 ru 汁，在网上找了好久的相似案例，最后终于解决了，先来看下网上常见的解决办法吧</p><h2 id="排查"><a href="#排查" class="headerlink" title="排查"></a>排查</h2><p>排查方法如下：</p><ol><li><p>mapper 接口和 mapper.xml 是否在同一个包（package）下？名字是否一样（仅后缀不同）？</p></li><li><p>mapper.xml 的命名空间（namespace）是否跟 mapper 接口的包名一致？</p></li><li><p>接口的方法名，与 xml 中的一条 sql 标签的 id 一致</p></li><li><p>如果接口中的返回值 List 集合（不知道其他集合也是），那么 xml 里面的配置，尽量用 resultMap（保证 resultMap 配置正确），不要用 resultType</p></li><li><p>如果你的项目是 maven 项目，请你在编译后，到接口所在目录看一看，很有可能是没有生产对应的 xml 文件，因为 maven 默认是不编译的，因此，你需要在你的 pom.xml 的 <code>&lt;build&gt; &lt;/build&gt;</code> 里面，加这么一段：</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resources</span>&gt;</span>    </span><br><span class="line">    <span class="tag">&lt;<span class="name">resource</span>&gt;</span>    </span><br><span class="line">        <span class="tag">&lt;<span class="name">directory</span>&gt;</span>src/main/java<span class="tag">&lt;/<span class="name">directory</span>&gt;</span>    </span><br><span class="line">        <span class="tag">&lt;<span class="name">includes</span>&gt;</span>    </span><br><span class="line">            <span class="tag">&lt;<span class="name">include</span>&gt;</span>**/*.xml<span class="tag">&lt;/<span class="name">include</span>&gt;</span>    </span><br><span class="line">        <span class="tag">&lt;/<span class="name">includes</span>&gt;</span>    </span><br><span class="line">        <span class="tag">&lt;<span class="name">filtering</span>&gt;</span>true<span class="tag">&lt;/<span class="name">filtering</span>&gt;</span>    </span><br><span class="line">    <span class="tag">&lt;/<span class="name">resource</span>&gt;</span>    </span><br><span class="line"><span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol><p>最后第五个方法解决了我的问题</p><p>如果以上方法都没有解决</p><div class="tabs" id="xiaojia"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="xiaojia-1">Dao 层代码</button><button type="button" class="tab " data-href="xiaojia-2">mapper.xml 代码</button><button type="button" class="tab " data-href="xiaojia-3">报错信息如下😥</button><button type="button" class="tab " data-href="xiaojia-4">解决办法😎</button></ul><div class="tab-contents"><div class="tab-item-content active" id="xiaojia-1"><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Repository</span>  </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">CustomDialogDao</span> &#123;  </span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">updateDialogByFrom2</span><span class="params">(<span class="meta">@Param(&quot;param&quot;)</span> CustomDialog param, <span class="meta">@Param(&quot;fromUser&quot;)</span> String fromUser, <span class="meta">@Param(&quot;appid&quot;)</span> String appid)</span>;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="xiaojia-2"><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span> ?&gt;</span>  </span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">mapper</span> <span class="keyword">PUBLIC</span> <span class="string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span> <span class="string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span> &gt;</span>  </span><br><span class="line">  </span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;com.benmu.mts.wx.center.service.dao.CustomDialogDao&quot;</span>&gt;</span>  </span><br><span class="line"><span class="tag">&lt;<span class="name">update</span> <span class="attr">id</span>=<span class="string">&quot;updateDialogByFrom2&quot;</span> <span class="attr">parameterType</span>=<span class="string">&quot;com.benmu.mts.wx.center.custom.bean.CustomDialog&quot;</span>&gt;</span>  </span><br><span class="line">        update custom_dialog  </span><br><span class="line">        <span class="tag">&lt;<span class="name">set</span>&gt;</span>  </span><br><span class="line">            <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;status != null&quot;</span>&gt;</span>  </span><br><span class="line">                status = #&#123;status&#125;  </span><br><span class="line">            <span class="tag">&lt;/<span class="name">if</span>&gt;</span>  </span><br><span class="line">        <span class="tag">&lt;/<span class="name">set</span>&gt;</span>  </span><br><span class="line">        where 1=1 and appid = #&#123;appid&#125; and fromUser = #&#123;fromUser&#125;  </span><br><span class="line">    <span class="tag">&lt;/<span class="name">update</span>&gt;</span>  </span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span>  </span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="xiaojia-3"><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter <span class="string">&#x27;status&#x27;</span> not found. Available parameters are [param, fromUser, appid, param3, param1, param2]  </span><br><span class="line">  </span><br><span class="line">    at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:<span class="number">76</span>)  </span><br><span class="line">    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:<span class="number">399</span>)  </span><br><span class="line">    at com.sun.proxy.$Proxy27.update(Unknown Source)  </span><br><span class="line">    at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:<span class="number">269</span>)  </span><br><span class="line">    at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:<span class="number">55</span>)  </span><br><span class="line">    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:<span class="number">53</span>)  </span><br><span class="line">    at com.sun.proxy.$Proxy28.updateDialogByFrom2(Unknown Source)  </span><br><span class="line">    at com.benmu.mts.wx.center.dao.CustomDialogDaoTest.updateDialogByFrom2(CustomDialogDaoTest.java:<span class="number">54</span>)  </span><br><span class="line">    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  </span><br><span class="line">    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:<span class="number">62</span>)  </span><br><span class="line">    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:<span class="number">43</span>)  </span><br><span class="line">    at java.lang.reflect.Method.invoke(Method.java:<span class="number">498</span>)  </span><br><span class="line">    at org.junit.runners.model.FrameworkMethod$<span class="number">1.</span>runReflectiveCall(FrameworkMethod.java:<span class="number">45</span>)  </span><br><span class="line">    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:<span class="number">15</span>)  </span><br><span class="line">    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:<span class="number">42</span>)  </span><br><span class="line">    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:<span class="number">20</span>) </span><br></pre></td></tr></table></figure></div><div class="tab-item-content" id="xiaojia-4"><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">update</span> <span class="attr">id</span>=<span class="string">&quot;updateDialogByFrom2&quot;</span> &gt;</span>  </span><br><span class="line">        update custom_dialog  </span><br><span class="line">        <span class="tag">&lt;<span class="name">set</span>&gt;</span>  </span><br><span class="line">            <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;param.status != null&quot;</span>&gt;</span>  </span><br><span class="line">                status = #&#123;param.status&#125;  </span><br><span class="line">            <span class="tag">&lt;/<span class="name">if</span>&gt;</span>  </span><br><span class="line">        <span class="tag">&lt;/<span class="name">set</span>&gt;</span>  </span><br><span class="line">        where 1=1 and appid = #&#123;appid&#125; and from_user = #&#123;fromUser&#125;  </span><br><span class="line"><span class="tag">&lt;/<span class="name">update</span>&gt;</span>  </span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><div class="note info flat"><p>Dao 层已经把 CustomDialog 定义成了 param，如果要使用 status，就要调用 param 这个对象的属性，否则 status 是找不到的</p></div>]]></content>
    
    
    <summary type="html">今天遇到 Mybatis 的报错，绞尽 ru 汁，在网上找了好久的相似案例，最后终于解决了，先来看下网上常见的解决办法吧</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="MyBatis" scheme="https://blog.imzjw.cn/tags/MyBatis/"/>
    
  </entry>
  
  <entry>
    <title>解决Tomcat启动乱码问题</title>
    <link href="https://blog.imzjw.cn/posts/fcb7/"/>
    <id>https://blog.imzjw.cn/posts/fcb7/</id>
    <published>2020-03-16T12:44:19.000Z</published>
    <updated>2020-03-16T12:44:19.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>Tomcat 启动时，不管是系统的控制台还是 idea 的控制台都有中文乱码，如下图</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fcb7/20200526152749.webp" alt="img"></p><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><ol><li><p>找到 Tomcat 目录下 conf 文件夹中的 <code>logging.properties</code> 文件</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fcb7/20200526152814.webp" alt="img"></p></li><li><p>打开 <code>logging.properties</code> 文件，找到文件中的 <code>java.util.logging.ConsoleHandler.encoding = UTF-8</code></p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fcb7/20200526152850.webp" alt="img"></p></li><li><p>将其中的 UTF-8 改为 GBK，保存后重启 Tomcat 服务，启动后就会看到刚才的乱码已经转换过来了。</p><p><img src= "https://npm.elemecdn.com/nanshen@latest/img/loading.webp" data-lazy-src="https://npm.elemecdn.com/cpdd/posts/fcb7/image-20200526152947977.webp" alt="img"></p></li></ol>]]></content>
    
    
    <summary type="html">Tomcat 启动时，不管是系统的控制台还是 idea 的控制台都有中文乱码，如下图，找到 Tomcat 目录下 conf 文件夹中的 logging.properties 文件，找到文件中</summary>
    
    
    
    <category term="Develop" scheme="https://blog.imzjw.cn/categories/Develop/"/>
    
    
    <category term="Tomcat" scheme="https://blog.imzjw.cn/tags/Tomcat/"/>
    
  </entry>
  
</feed>
