<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>麻绳先生</title>
  
  <subtitle>做一些记录性的工作</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://zkalan.com/"/>
  <updated>2025-06-10T19:14:52.024Z</updated>
  <id>http://zkalan.com/</id>
  
  <author>
    <name>Zhang Kai</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Spring Cloud 自定义负载均衡器和 FeignClient</title>
    <link href="http://zkalan.com/Spring%20Cloud%20%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%99%A8.html"/>
    <id>http://zkalan.com/Spring%20Cloud%20%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%99%A8.html</id>
    <published>2023-05-20T13:49:53.000Z</published>
    <updated>2025-06-10T19:14:52.024Z</updated>
    
    <content type="html"><![CDATA[<p>有这样一个问题，如何在负载均衡的时候自定义自己的逻辑，比如根据这次请求的 <code>FeignClient</code> 配置来过滤某些特别的实例呢？</p><h2 id="1-用-Interceptor-拦截请求"><a href="#1-用-Interceptor-拦截请求" class="headerlink" title="1. 用 Interceptor 拦截请求"></a>1. 用 Interceptor 拦截请求</h2><h2 id="2-用ThreadLocal-变量保存-Request"><a href="#2-用ThreadLocal-变量保存-Request" class="headerlink" title="2. 用ThreadLocal 变量保存 Request"></a>2. 用ThreadLocal 变量保存 Request</h2><h2 id="3-自定义负载均衡器"><a href="#3-自定义负载均衡器" class="headerlink" title="3. 自定义负载均衡器"></a>3. 自定义负载均衡器</h2><h2 id="4-从-Request-中拿到-FeignClient-注解配置"><a href="#4-从-Request-中拿到-FeignClient-注解配置" class="headerlink" title="4. 从 Request 中拿到 FeignClient 注解配置"></a>4. 从 Request 中拿到 FeignClient 注解配置</h2><h2 id="5-其他细节"><a href="#5-其他细节" class="headerlink" title="5. 其他细节"></a>5. 其他细节</h2><h3 id="5-1-不要自己声明负载均衡器的-Bean-了"><a href="#5-1-不要自己声明负载均衡器的-Bean-了" class="headerlink" title="5.1 不要自己声明负载均衡器的 Bean 了"></a>5.1 不要自己声明负载均衡器的 Bean 了</h3><h3 id="5-2-LoadBalancerClient-就够用了，还有-LoadBalancerClients"><a href="#5-2-LoadBalancerClient-就够用了，还有-LoadBalancerClients" class="headerlink" title="5.2 @LoadBalancerClient 就够用了，还有 @LoadBalancerClients"></a>5.2 @LoadBalancerClient 就够用了，还有 @LoadBalancerClients</h3>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;有这样一个问题，如何在负载均衡的时候自定义自己的逻辑，比如根据这次请求的 &lt;code&gt;FeignClient&lt;/code&gt; 配置来过滤某些特别的实例呢？&lt;/p&gt;
&lt;h2 id=&quot;1-用-Interceptor-拦截请求&quot;&gt;&lt;a href=&quot;#1-用-Interceptor-
      
    
    </summary>
    
    
    
      <category term="Spring Cloud, FeignClient" scheme="http://zkalan.com/tags/Spring-Cloud-FeignClient/"/>
    
  </entry>
  
  <entry>
    <title>IDEA插件开发(一)</title>
    <link href="http://zkalan.com/IDEA%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91(%E4%B8%80).html"/>
    <id>http://zkalan.com/IDEA%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91(%E4%B8%80).html</id>
    <published>2022-09-09T14:38:52.000Z</published>
    <updated>2025-06-10T19:14:52.024Z</updated>
    
    <content type="html"><![CDATA[<h2 id="IDEA-插件"><a href="#IDEA-插件" class="headerlink" title="IDEA 插件"></a>IDEA 插件</h2><p>IDEA 插件可以实现很多功能，自定义语言、更丰富的代码提示和挂高亮、代码生成、通过 PSI 操作源码。而我现在就在通过 PSI 相关方法为 spring cloud 的 api 方法生成 trpc 桩代码。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;IDEA-插件&quot;&gt;&lt;a href=&quot;#IDEA-插件&quot; class=&quot;headerlink&quot; title=&quot;IDEA 插件&quot;&gt;&lt;/a&gt;IDEA 插件&lt;/h2&gt;&lt;p&gt;IDEA 插件可以实现很多功能，自定义语言、更丰富的代码提示和挂高亮、代码生成、通过 PSI 操作源
      
    
    </summary>
    
    
      <category term="IDEA插件" scheme="http://zkalan.com/categories/IDEA%E6%8F%92%E4%BB%B6/"/>
    
    
      <category term="IDEA" scheme="http://zkalan.com/tags/IDEA/"/>
    
      <category term="插件" scheme="http://zkalan.com/tags/%E6%8F%92%E4%BB%B6/"/>
    
  </entry>
  
  <entry>
    <title>分享：github-action-部署静态资源到阿里云</title>
    <link href="http://zkalan.com/%E5%88%86%E4%BA%AB%EF%BC%9Agithub-action-%E9%83%A8%E7%BD%B2%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E5%88%B0%E9%98%BF%E9%87%8C%E4%BA%91.html"/>
    <id>http://zkalan.com/%E5%88%86%E4%BA%AB%EF%BC%9Agithub-action-%E9%83%A8%E7%BD%B2%E9%9D%99%E6%80%81%E8%B5%84%E6%BA%90%E5%88%B0%E9%98%BF%E9%87%8C%E4%BA%91.html</id>
    <published>2022-06-11T12:53:03.000Z</published>
    <updated>2025-06-10T19:14:52.026Z</updated>
    
    <content type="html"><![CDATA[<p>这里是一个工作流分享，通过 github action 将 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><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="attr">name:</span> <span class="string">Hexo</span> <span class="string">build</span> <span class="string">and</span> <span class="string">deploy</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 class="string">[</span> <span class="string">master</span> <span class="string">]</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><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="attr">    - name:</span> <span class="string">Checkout</span></span><br><span class="line"><span class="attr">      uses:</span> <span class="string">actions/checkout@v3</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><br><span class="line"><span class="attr">    - name:</span> <span class="string">Set</span> <span class="string">Node</span> <span class="number">12</span></span><br><span class="line"><span class="attr">      uses:</span> <span class="string">actions/setup-node@v3</span></span><br><span class="line"><span class="attr">      with:</span></span><br><span class="line"><span class="attr">        node-version:</span> <span class="number">12</span></span><br><span class="line"><span class="attr">    - name:</span> <span class="string">Install</span> <span class="string">and</span> <span class="string">Build</span></span><br><span class="line"><span class="attr">      run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">        npm install</span></span><br><span class="line"><span class="string">        npm install -g hexo-cli</span></span><br><span class="line"><span class="string">        hexo clean</span></span><br><span class="line"><span class="string">        hexo g</span></span><br><span class="line"><span class="string"></span><span class="attr">    - name:</span> <span class="string">ssh</span> <span class="string">deploy</span></span><br><span class="line"><span class="attr">      uses:</span> <span class="string">easingthemes/ssh-deploy@v2.2.11</span></span><br><span class="line"><span class="attr">      env:</span></span><br><span class="line"><span class="attr">        SSH_PRIVATE_KEY:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.ALIYUN_SERVER_ACCESS_TOKEN</span> <span class="string">&#125;&#125;</span></span><br><span class="line"><span class="attr">        ARGS:</span> <span class="string">"-avz --delete"</span></span><br><span class="line"><span class="attr">        SOURCE:</span> <span class="string">"public"</span></span><br><span class="line"><span class="attr">        REMOTE_HOST:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.ALIYUN_SERVER_HOST</span> <span class="string">&#125;&#125;</span></span><br><span class="line"><span class="attr">        REMOTE_USER:</span> <span class="string">"root"</span></span><br><span class="line"><span class="attr">        TARGET:</span> <span class="string">"/home/github_actions_blog/"</span></span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;这里是一个工作流分享，通过 github action 将 hexo 静态网站资源自动部署到阿里云服务器。&lt;/p&gt;
&lt;figure class=&quot;highlight yaml&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;
      
    
    </summary>
    
    
      <category term="分享" scheme="http://zkalan.com/categories/%E5%88%86%E4%BA%AB/"/>
    
    
      <category term="github action" scheme="http://zkalan.com/tags/github-action/"/>
    
  </entry>
  
  <entry>
    <title>Eledn Ring 预计在 2022 年 2 月 25 日发售</title>
    <link href="http://zkalan.com/Eledn-Ring-%E9%A2%84%E8%AE%A1%E5%9C%A8-2022-%E5%B9%B4-2-%E6%9C%88-25-%E6%97%A5%E5%8F%91%E5%94%AE.html"/>
    <id>http://zkalan.com/Eledn-Ring-%E9%A2%84%E8%AE%A1%E5%9C%A8-2022-%E5%B9%B4-2-%E6%9C%88-25-%E6%97%A5%E5%8F%91%E5%94%AE.html</id>
    <published>2021-11-20T05:28:14.000Z</published>
    <updated>2025-06-10T19:14:52.024Z</updated>
    
    <content type="html"><![CDATA[<p>这是第一次延期后的时间，希望只有这一次延期，不要再有下次。</p><p><img src="../img/eldenring.jpg" alt="Elden Ring"></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;这是第一次延期后的时间，希望只有这一次延期，不要再有下次。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../img/eldenring.jpg&quot; alt=&quot;Elden Ring&quot;&gt;&lt;/p&gt;

      
    
    </summary>
    
    
      <category term="兴趣" scheme="http://zkalan.com/categories/%E5%85%B4%E8%B6%A3/"/>
    
    
      <category term="艾尔登法环" scheme="http://zkalan.com/tags/%E8%89%BE%E5%B0%94%E7%99%BB%E6%B3%95%E7%8E%AF/"/>
    
      <category term="Elden Ring" scheme="http://zkalan.com/tags/Elden-Ring/"/>
    
  </entry>
  
  <entry>
    <title>习近平发表二〇二一年新年贺词</title>
    <link href="http://zkalan.com/%E4%B9%A0%E8%BF%91%E5%B9%B3%E5%8F%91%E8%A1%A8%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%80%E5%B9%B4%E6%96%B0%E5%B9%B4%E8%B4%BA%E8%AF%8D.html"/>
    <id>http://zkalan.com/%E4%B9%A0%E8%BF%91%E5%B9%B3%E5%8F%91%E8%A1%A8%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%80%E5%B9%B4%E6%96%B0%E5%B9%B4%E8%B4%BA%E8%AF%8D.html</id>
    <published>2021-01-04T01:21:52.000Z</published>
    <updated>2025-06-10T19:14:52.026Z</updated>
    
    <content type="html"><![CDATA[<p>新年前夕，国家主席习近平通过中央广播电视总台和互联网，发表了二〇二一年新年贺词。全文如下：</p><p>大家好！2021年的脚步越来越近，我在北京向大家致以新年的美好祝福！</p><p>2020年是极不平凡的一年。面对突如其来的新冠肺炎疫情，我们以人民至上、生命至上诠释了人间大爱，用众志成城、坚忍不拔书写了抗疫史诗。在共克时艰的日子里，有逆行出征的豪迈，有顽强不屈的坚守，有患难与共的担当，有英勇无畏的牺牲，有守望相助的感动。从白衣天使到人民子弟兵，从科研人员到社区工作者，从志愿者到工程建设者，从古稀老人到“90后”、“00后”青年一代，无数人以生命赴使命、用挚爱护苍生，将涓滴之力汇聚成磅礴伟力，构筑起守护生命的铜墙铁壁。一个个义无反顾的身影，一次次心手相连的接力，一幕幕感人至深的场景，生动展示了伟大抗疫精神。平凡铸就伟大，英雄来自人民。每个人都了不起！向所有不幸感染的病患者表示慰问！向所有平凡的英雄致敬！我为伟大的祖国和人民而骄傲，为自强不息的民族精神而自豪！</p><p>艰难方显勇毅，磨砺始得玉成。我们克服疫情影响，统筹疫情防控和经济社会发展取得重大成果。“十三五”圆满收官，“十四五”全面擘画。新发展格局加快构建，高质量发展深入实施。我国在世界主要经济体中率先实现正增长，预计2020年国内生产总值迈上百万亿元新台阶。粮食生产喜获“十七连丰”。“天问一号”、“嫦娥五号”、“奋斗者”号等科学探测实现重大突破。海南自由贸易港建设蓬勃展开。我们还抵御了严重洪涝灾害，广大军民不畏艰险，同心协力抗洪救灾，努力把损失降到了最低。我到13个省区市考察时欣喜看到，大家认真细致落实防疫措施，争分夺秒复工复产，全力以赴创新创造，神州大地自信自强、充满韧劲，一派只争朝夕、生机勃勃的景象。</p><p>2020年，全面建成小康社会取得伟大历史性成就，决战脱贫攻坚取得决定性胜利。我们向深度贫困堡垒发起总攻，啃下了最难啃的“硬骨头”。历经8年，现行标准下近1亿农村贫困人口全部脱贫，832个贫困县全部摘帽。这些年，我去了全国14个集中连片特困地区，乡亲们愚公移山的干劲，广大扶贫干部倾情投入的奉献，时常浮现在脑海。我们还要咬定青山不放松，脚踏实地加油干，努力绘就乡村振兴的壮美画卷，朝着共同富裕的目标稳步前行。</p><p>今年，我们隆重庆祝深圳等经济特区建立40周年、上海浦东开发开放30周年。置身春潮涌动的南海之滨、绚丽多姿的黄浦江畔，令人百感交集，先行先试变成了示范引领，探索创新成为了创新引领。改革开放创造了发展奇迹，今后还要以更大气魄深化改革、扩大开放，续写更多“春天的故事”。</p><p>大道不孤，天下一家。经历了一年来的风雨，我们比任何时候都更加深切体会到人类命运共同体的意义。我同国际上新老朋友进行了多次通话，出席了多场“云会议”，谈得最多的就是和衷共济、团结抗疫。疫情防控任重道远。世界各国人民要携起手来，风雨同舟，早日驱散疫情的阴霾，努力建设更加美好的地球家园。</p><p>2021年是中国共产党百年华诞。百年征程波澜壮阔，百年初心历久弥坚。从上海石库门到嘉兴南湖，一艘小小红船承载着人民的重托、民族的希望，越过急流险滩，穿过惊涛骇浪，成为领航中国行稳致远的巍巍巨轮。胸怀千秋伟业，恰是百年风华。我们秉持以人民为中心，永葆初心、牢记使命，乘风破浪、扬帆远航，一定能实现中华民族伟大复兴。</p><p>站在“两个一百年”的历史交汇点，全面建设社会主义现代化国家新征程即将开启。征途漫漫，惟有奋斗。我们通过奋斗，披荆斩棘，走过了万水千山。我们还要继续奋斗，勇往直前，创造更加灿烂的辉煌！</p><p>此时此刻，华灯初上，万家团圆。新年将至，惟愿山河锦绣、国泰民安！惟愿和顺致祥、幸福美满！</p><p>谢谢大家！</p><p>来源：新华社</p><p>本期编辑：胡程远、李娜</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;新年前夕，国家主席习近平通过中央广播电视总台和互联网，发表了二〇二一年新年贺词。全文如下：&lt;/p&gt;
&lt;p&gt;大家好！2021年的脚步越来越近，我在北京向大家致以新年的美好祝福！&lt;/p&gt;
&lt;p&gt;2020年是极不平凡的一年。面对突如其来的新冠肺炎疫情，我们以人民至上、生命至上诠释
      
    
    </summary>
    
    
      <category term="文章" scheme="http://zkalan.com/categories/%E6%96%87%E7%AB%A0/"/>
    
    
      <category term="新年贺词" scheme="http://zkalan.com/tags/%E6%96%B0%E5%B9%B4%E8%B4%BA%E8%AF%8D/"/>
    
      <category term="2021" scheme="http://zkalan.com/tags/2021/"/>
    
  </entry>
  
  <entry>
    <title>leetcode216</title>
    <link href="http://zkalan.com/leetcode216.html"/>
    <id>http://zkalan.com/leetcode216.html</id>
    <published>2020-09-11T07:54:07.000Z</published>
    <updated>2025-06-10T19:14:52.025Z</updated>
    
    <content type="html"><![CDATA[<p>这是因为疫情原因，离开校园，无法获得密钥发布文章的8个多月以来，第一篇文章。<br>以此测试一下博客环境是否正常。</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="class"><span class="keyword">class</span> <span class="title">Solution</span> </span>&#123;</span><br><span class="line">    List&lt;List&lt;Integer&gt;&gt; result = <span class="keyword">new</span> LinkedList&lt;&gt;();</span><br><span class="line">    <span class="keyword">public</span> List&lt;List&lt;Integer&gt;&gt; combinationSum3(<span class="keyword">int</span> k, <span class="keyword">int</span> n) &#123;</span><br><span class="line">        backtrace(<span class="keyword">new</span> LinkedList&lt;Integer&gt;(), <span class="number">1</span>, k, n, k);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">backtrace</span><span class="params">(List&lt;Integer&gt; path, <span class="keyword">int</span> start, <span class="keyword">int</span> k, <span class="keyword">int</span> n, <span class="keyword">int</span> old)</span></span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(k == <span class="number">0</span> &amp;&amp; path.size() == old &amp;&amp; n == <span class="number">0</span>)&#123;</span><br><span class="line">            result.add(<span class="keyword">new</span> LinkedList&lt;Integer&gt;(path));</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(start &gt; <span class="number">9</span> || k &lt; <span class="number">0</span>) <span class="keyword">return</span>;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i = start; i &lt; <span class="number">10</span> &amp;&amp; i &lt;= n; ++i)&#123;</span><br><span class="line">            path.add(i);</span><br><span class="line">            backtrace(path, i+<span class="number">1</span>, k-<span class="number">1</span>, n-i, old);</span><br><span class="line">            path.remove(path.size()-<span class="number">1</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>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;这是因为疫情原因，离开校园，无法获得密钥发布文章的8个多月以来，第一篇文章。&lt;br&gt;以此测试一下博客环境是否正常。&lt;/p&gt;
&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span cla
      
    
    </summary>
    
    
    
      <category term="leetcode" scheme="http://zkalan.com/tags/leetcode/"/>
    
  </entry>
  
  <entry>
    <title>PyQt5小程序上传图片到七牛云</title>
    <link href="http://zkalan.com/PyQt5%E5%B0%8F%E7%A8%8B%E5%BA%8F%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87%E5%88%B0%E4%B8%83%E7%89%9B%E4%BA%91.html"/>
    <id>http://zkalan.com/PyQt5%E5%B0%8F%E7%A8%8B%E5%BA%8F%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87%E5%88%B0%E4%B8%83%E7%89%9B%E4%BA%91.html</id>
    <published>2020-01-05T13:50:18.000Z</published>
    <updated>2025-06-10T19:14:52.024Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>github地址<br><a href="https://github.com/zkalan/qiniu-image.git" target="_blank" rel="noopener">https://github.com/zkalan/qiniu-image.git</a></p></blockquote><h2 id="绘制软件界面"><a href="#绘制软件界面" class="headerlink" title="绘制软件界面"></a>绘制软件界面</h2><p>使用Qt Designer绘制程序界面，设置图标，修改控件id等。这个过程还包括几个配置步骤：</p><ul><li>在pycharm中安装PyQt5</li><li>在pycharm中安装PyQt5-tools</li><li>配置pycharm，方便的通过tools界面启动dedigner和其他工具</li></ul><h2 id="slots和signals"><a href="#slots和signals" class="headerlink" title="slots和signals"></a>slots和signals</h2><p>这是两个PyQt中的概念，signal就是信号，是动作的发出者；slot就是槽，是动作的相应者。代码如下：</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="keyword">import</span> sys, os</span><br><span class="line"><span class="keyword">if</span> hasattr(sys, <span class="string">'frozen'</span>):</span><br><span class="line">    os.environ[<span class="string">'PATH'</span>] = sys._MEIPASS + <span class="string">";"</span> + os.environ[<span class="string">'PATH'</span>]</span><br><span class="line"><span class="keyword">from</span> ui <span class="keyword">import</span> mainwindow</span><br><span class="line"><span class="keyword">from</span> PyQt5 <span class="keyword">import</span> QtGui, QtCore</span><br><span class="line"><span class="keyword">from</span> PyQt5.QtWidgets <span class="keyword">import</span> QMainWindow, QApplication, QMessageBox, QFileDialog</span><br><span class="line"><span class="keyword">from</span> utils <span class="keyword">import</span> uploadtoqiniu</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">WindowService</span><span class="params">(QMainWindow, mainwindow.Ui_MainWindow)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></span><br><span class="line">        super(WindowService, self).__init__()</span><br><span class="line">        self.setupUi(self)</span><br><span class="line">        <span class="comment"># bind slots and signals</span></span><br><span class="line">        self.pb_select.clicked.connect(self.pb_select_service)</span><br><span class="line"></span><br><span class="line">        self.pb_copy_url.clicked.connect(self.pb_copy_url_service)</span><br><span class="line">        self.pb_copy_markdown.clicked.connect(self.pb_copy_markdown_service)</span><br><span class="line">        self.pb_upload.clicked.connect(self.pb_upload_service)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">pb_select_service</span><span class="params">(self)</span>:</span></span><br><span class="line">        filename, filetype = QFileDialog.getOpenFileName(self,</span><br><span class="line">                                                         <span class="string">'选择文件'</span>,</span><br><span class="line">                                                         os.getcwd(),</span><br><span class="line">                                                         <span class="string">"Images (*.jpg;*.jpeg;*.gif;*.png;*.ico);;All Files (*)"</span>)</span><br><span class="line">        <span class="keyword">if</span> filename == <span class="string">''</span>:</span><br><span class="line">            print(<span class="string">'filename is'</span> + filename)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        self.le_selectimage.setText(filename)</span><br><span class="line">        print(<span class="string">'filename is'</span> + filename)</span><br><span class="line">        print(<span class="string">'文件筛选器类型：'</span>, filetype)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">pb_upload_service</span><span class="params">(self)</span>:</span></span><br><span class="line">        filepath = self.le_selectimage.text()</span><br><span class="line">        <span class="keyword">if</span> filepath == <span class="string">''</span>:</span><br><span class="line">            self.maessage_box(<span class="string">'select a image'</span>)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">if</span> os.path.exists(<span class="string">'settings.cfg'</span>):</span><br><span class="line">                back_url = uploadtoqiniu.upload(filepath)</span><br><span class="line">                self.le_url.setText(back_url)</span><br><span class="line">                self.le_md.setText(<span class="string">'![]('</span> + back_url + <span class="string">')'</span>)</span><br><span class="line">                img = QtGui.QImage(filepath)</span><br><span class="line">                scale = img.size().width()/<span class="number">411</span> <span class="keyword">if</span> ((img.size().width()/<span class="number">411</span>) &gt; (img.size().height()/<span class="number">201</span>)) <span class="keyword">else</span> img.size().height()/<span class="number">201</span></span><br><span class="line">                scale_width = img.size().width()/scale</span><br><span class="line">                scale_height = img.size().height() / scale</span><br><span class="line">                size = QtCore.QSize(scale_width, scale_height)</span><br><span class="line">                image = QtGui.QPixmap.fromImage(img.scaled(size, QtCore.Qt.IgnoreAspectRatio))</span><br><span class="line">                self.l_preview.setPixmap(image)</span><br><span class="line">                print(image.size())</span><br><span class="line">                print(type(image.size()))</span><br><span class="line">                self.maessage_box(<span class="string">'Success'</span>)</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                self.maessage_box(<span class="string">'check setting.cfg'</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">pb_copy_url_service</span><span class="params">(self)</span>:</span></span><br><span class="line">        clipboard = QApplication.clipboard()</span><br><span class="line">        url = self.le_url.text()</span><br><span class="line">        clipboard.setText(url)</span><br><span class="line">        self.maessage_box(<span class="string">'copy to clipkboard'</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">pb_copy_markdown_service</span><span class="params">(self)</span>:</span></span><br><span class="line">        clipboard = QApplication.clipboard()</span><br><span class="line">        md_url = self.le_md.text()</span><br><span class="line">        clipboard.setText(md_url)</span><br><span class="line">        self.maessage_box(<span class="string">'copy to clipkboard'</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">maessage_box</span><span class="params">(self, message, title=<span class="string">'information'</span>)</span>:</span></span><br><span class="line">        box = QMessageBox(self)</span><br><span class="line">        box.setIcon(QMessageBox.Information)</span><br><span class="line">        box.setText(message)</span><br><span class="line">        box.setWindowTitle(title)</span><br><span class="line">        box.setStandardButtons(QMessageBox.Ok)</span><br><span class="line">        box.button(QMessageBox.Ok).animateClick(<span class="number">2</span>*<span class="number">1000</span>)</span><br><span class="line">        box.exec_()</span><br></pre></td></tr></table></figure><h2 id="使用pyinstaller打包"><a href="#使用pyinstaller打包" class="headerlink" title="使用pyinstaller打包"></a>使用pyinstaller打包</h2><p>pyinstaller打包总是问题百出，PyQt5自己也有不少bug。遇到这些问题</p><h3 id="ImportError-unable-to-find-Qt5Core-dll-on-PATH"><a href="#ImportError-unable-to-find-Qt5Core-dll-on-PATH" class="headerlink" title="ImportError: unable to find Qt5Core.dll on PATH"></a>ImportError: unable to find Qt5Core.dll on PATH</h3><p>解决办法如下</p><blockquote><p><a href="https://blog.csdn.net/zwyact/article/details/99778898" target="_blank" rel="noopener">https://blog.csdn.net/zwyact/article/details/99778898</a><br>在主程序中pyqt5库import之前就对系统变量进行手动设置</p></blockquote><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys, os</span><br><span class="line"><span class="keyword">if</span> hasattr(sys, <span class="string">'frozen'</span>):</span><br><span class="line">    os.environ[<span class="string">'PATH'</span>] = sys._MEIPASS + <span class="string">";"</span> + os.environ[<span class="string">'PATH'</span>]</span><br></pre></td></tr></table></figure><h3 id="NameError-name-‘exit’-is-not-defined"><a href="#NameError-name-‘exit’-is-not-defined" class="headerlink" title="NameError: name ‘exit’ is not defined"></a>NameError: name ‘exit’ is not defined</h3><p>解决办法就是这样写sys.exit</p><h2 id="效果预览"><a href="#效果预览" class="headerlink" title="效果预览"></a>效果预览</h2><p>settings.cfg是配置文件，其中需要配置各个字段。可以配置是否使用水印。</p><h3 id="主界面"><a href="#主界面" class="headerlink" title="主界面"></a>主界面</h3><p><img src="http://cdn.zkalan.com/VJOdMYuW8Ti4om0gBQvx08Ckr44=/FnGYihfO9pvjDnA77RSIAtexgUkK" alt></p><h3 id="上传图片"><a href="#上传图片" class="headerlink" title="上传图片"></a>上传图片</h3><p>上传完图片还能快速获取访问链接。</p><p><img src="http://cdn.zkalan.com/VJOdMYuW8Ti4om0gBQvx08Ckr44=/FmM6w11zg5p5KhkNlnekF3mYpT6a" alt></p><blockquote><p>github地址<br><a href="https://github.com/zkalan/qiniu-image.git" target="_blank" rel="noopener">https://github.com/zkalan/qiniu-image.git</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      
      
        &lt;blockquote&gt;
&lt;p&gt;github地址&lt;br&gt;&lt;a href=&quot;https://github.com/zkalan/qiniu-image.git&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/zkalan/qin
      
    
    </summary>
    
    
      <category term="PyQt5" scheme="http://zkalan.com/categories/PyQt5/"/>
    
    
      <category term="pyqt5" scheme="http://zkalan.com/tags/pyqt5/"/>
    
      <category term="python" scheme="http://zkalan.com/tags/python/"/>
    
      <category term="七牛云" scheme="http://zkalan.com/tags/%E4%B8%83%E7%89%9B%E4%BA%91/"/>
    
      <category term="pyinstaller" scheme="http://zkalan.com/tags/pyinstaller/"/>
    
      <category term="pycharm" scheme="http://zkalan.com/tags/pycharm/"/>
    
  </entry>
  
  <entry>
    <title>spark第一次笔记</title>
    <link href="http://zkalan.com/spark%E7%AC%AC%E4%B8%80%E6%AC%A1%E7%AC%94%E8%AE%B0.html"/>
    <id>http://zkalan.com/spark%E7%AC%AC%E4%B8%80%E6%AC%A1%E7%AC%94%E8%AE%B0.html</id>
    <published>2019-12-28T07:47:52.000Z</published>
    <updated>2025-06-10T19:14:52.025Z</updated>
    
    <content type="html"><![CDATA[<h2 id="hadoop历史"><a href="#hadoop历史" class="headerlink" title="hadoop历史"></a>hadoop历史</h2><p>2011年发布1.0版本，2012年发布稳定版，2013发布2.x版本（Yarn）</p><h3 id="缺点"><a href="#缺点" class="headerlink" title="缺点"></a>缺点</h3><ul><li>基于数据集的计算，所以面向数据。从存储介质中获取数据，然后进行计算，最后将结果存储到介质中。所以主要应用于一次性计算，不适合数据挖掘和机器学习这些迭代计算和图形挖掘计算。</li><li>mapreduce基于文件存储介质的操作，性能差</li><li>mapreduce和hadoop紧密耦合</li></ul><h3 id="Yarn版本"><a href="#Yarn版本" class="headerlink" title="Yarn版本"></a>Yarn版本</h3><p>ResourceManager、ApplicationMaster、Driver、NodeManager</p><h2 id="spark历史"><a href="#spark历史" class="headerlink" title="spark历史"></a>spark历史</h2><p>2013年6月正式发布，spark基于hadoop1.x架构思想设计思想。spark计算基于内存，并且基于Scala语法开发，所以天生适合迭代式计算。</p><p><strong>HDFS-Yarn-Spark</strong></p><h2 id="Spark下载地址"><a href="#Spark下载地址" class="headerlink" title="Spark下载地址"></a>Spark下载地址</h2><p><a href="http://spark.apache.org" target="_blank" rel="noopener">http://spark.apache.org</a></p><h2 id="重要角色"><a href="#重要角色" class="headerlink" title="重要角色"></a>重要角色</h2><h3 id="Driver（驱动器）"><a href="#Driver（驱动器）" class="headerlink" title="Driver（驱动器）"></a>Driver（驱动器）</h3><h3 id="Executer（执行器）"><a href="#Executer（执行器）" class="headerlink" title="Executer（执行器）"></a>Executer（执行器）</h3><h3 id="Spark-Yarn运行模式简图"><a href="#Spark-Yarn运行模式简图" class="headerlink" title="Spark-Yarn运行模式简图"></a>Spark-Yarn运行模式简图</h3><p><img src="http://cdn.zkalan.com/Yarn%E8%BF%90%E8%A1%8C%E6%A8%A1%E5%BC%8F%E4%BB%8B%E7%BB%8D.png" alt="Spark-Yarn运行模式简图"></p><h2 id="Standalone模式"><a href="#Standalone模式" class="headerlink" title="Standalone模式"></a>Standalone模式</h2><h2 id="RDD"><a href="#RDD" class="headerlink" title="RDD"></a>RDD</h2><p>RDD(Resilient Distributed Dataset)称为弹性分布式数据集，是Spark中最基本的数据或计算抽象。代码中是一个抽象类，代表一个不可变、可分区、里面的元素可进行并行计算的集合。</p><h3 id="RDD属性"><a href="#RDD属性" class="headerlink" title="RDD属性"></a>RDD属性</h3><ul><li>一组分区Partition，即数据集的基本组成单位</li><li>一个计算每个分区的函数</li><li>RDD之间的依赖关系</li><li>一个Partitioner，即RDD的分片函数</li><li>一个列表，存储存取每个Partiton的优先位置preferred location</li></ul><p>大数据窍门：<strong>移动数据不如移动计算</strong></p><h3 id="RDD特点"><a href="#RDD特点" class="headerlink" title="RDD特点"></a>RDD特点</h3><p>RDD表示只读的分区的数据集，对RDD进行改动，只能通过RDD的转换操作，由一个RDD得到一个新的RDD，新的RDD包含了从其他RDD衍生所必须的信息，RDDs之间存在依赖，RDD的执行是按照血缘关系延时计算的。如果血缘关系较长，可以通过持久化RDD来切断血缘关系。</p><p>Spark中所有RDD方法都称为算子，共分为两大类，转化算子和行动算子。</p><h3 id="缓存"><a href="#缓存" class="headerlink" title="缓存"></a>缓存</h3><p>如果应用程序多次使用同一个RDD，可以将该RDD缓存起来。</p><h3 id="RDD的创建"><a href="#RDD的创建" class="headerlink" title="RDD的创建"></a>RDD的创建</h3><p>Spark中创建RDD的方法有三种：从集合中创建、从外部存储创建、从其他RDD创建。</p><h4 id="集合创建"><a href="#集合创建" class="headerlink" title="集合创建"></a>集合创建</h4><figure class="highlight scala"><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="comment">//前者调用后者</span></span><br><span class="line">sc.makeRDD(<span class="type">List</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>))</span><br><span class="line">sc.parallelize(<span class="type">Array</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>))</span><br></pre></td></tr></table></figure><h4 id="外部存储创建"><a href="#外部存储创建" class="headerlink" title="外部存储创建"></a>外部存储创建</h4><figure class="highlight scala"><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="comment">//默认情况下，可以读取项目路径，也可以读取其他HDFS路径</span></span><br><span class="line"><span class="keyword">val</span> value:<span class="type">RDD</span>[<span class="type">String</span>] = sc.textField(<span class="string">"in"</span>)</span><br><span class="line"><span class="comment">//涉及hadoop读取文件的分片规则</span></span><br></pre></td></tr></table></figure><h3 id="RDD的转换"><a href="#RDD的转换" class="headerlink" title="RDD的转换"></a>RDD的转换</h3><h4 id="Value类型"><a href="#Value类型" class="headerlink" title="Value类型"></a>Value类型</h4><h5 id="map-function"><a href="#map-function" class="headerlink" title="map(function)"></a>map(function)</h5><p>返回一个新的RDD，该RDD由每一个输入元素经过function函数转换后组成。例如通过一个数组RDD得到一个每个元素被乘以2的新的RDD。</p><h5 id="mapPartitions"><a href="#mapPartitions" class="headerlink" title="mapPartitions"></a>mapPartitions</h5><p>mapPartitions效率优于map算子，减少了发送到执行器执行交互次数。但是可能会出现内存溢出OOM。一次处理一个分区的数据。</p><h5 id="mapPartitionsWithIndex-func"><a href="#mapPartitionsWithIndex-func" class="headerlink" title="mapPartitionsWithIndex(func)"></a>mapPartitionsWithIndex(func)</h5><p>作用是，func带有一个整数参数表示分片的索引值，因此在类型为T的RDD上运行时，func的函数类型必须是(Int, Interator[T]) -&gt; Iterator[U]。</p><h5 id="Driver和Executor关系"><a href="#Driver和Executor关系" class="headerlink" title="Driver和Executor关系"></a>Driver和Executor关系</h5><p>Driver就是创建Spark上下文对象的应用程序，Executor就是用于提取任务并执行。</p><h5 id="flatMap"><a href="#flatMap" class="headerlink" title="flatMap"></a>flatMap</h5><h5 id="glom"><a href="#glom" class="headerlink" title="glom"></a>glom</h5><p>将每一个分区形成一个数组，形成新的RDD类型为RDD[Array[T]]。</p><h5 id="groupBy-amp-filter"><a href="#groupBy-amp-filter" class="headerlink" title="groupBy &amp; filter"></a>groupBy &amp; filter</h5><p>分组，按照传入函数的返回值进行分组，将相同的key对应的值放入一个迭代器。</p><h5 id="sample-withRepalcement-fraction-seed"><a href="#sample-withRepalcement-fraction-seed" class="headerlink" title="sample(withRepalcement, fraction, seed)"></a>sample(withRepalcement, fraction, seed)</h5><p>以指定的随机种子随机抽样出数量为fraction的数据，withReplacement表示抽出的数据是否放回，true表示有放回，seed用于指定随机数生成器种子。</p><h5 id="distinct"><a href="#distinct" class="headerlink" title="distinct"></a>distinct</h5><h5 id="coalesce"><a href="#coalesce" class="headerlink" title="coalesce"></a>coalesce</h5><h5 id="repartition-amp-sortBy"><a href="#repartition-amp-sortBy" class="headerlink" title="repartition &amp; sortBy"></a>repartition &amp; sortBy</h5><h4 id="双Value类型交互"><a href="#双Value类型交互" class="headerlink" title="双Value类型交互"></a>双Value类型交互</h4><h5 id="union"><a href="#union" class="headerlink" title="union"></a>union</h5><h5 id="cartesian"><a href="#cartesian" class="headerlink" title="cartesian"></a>cartesian</h5><h4 id="Key-Value类型"><a href="#Key-Value类型" class="headerlink" title="Key-Value类型"></a>Key-Value类型</h4><h5 id="partitionBy"><a href="#partitionBy" class="headerlink" title="partitionBy"></a>partitionBy</h5><h5 id="groupBykey"><a href="#groupBykey" class="headerlink" title="groupBykey"></a>groupBykey</h5><h5 id="reduceBykey"><a href="#reduceBykey" class="headerlink" title="reduceBykey"></a>reduceBykey</h5><h5 id="aggregateBykey"><a href="#aggregateBykey" class="headerlink" title="aggregateBykey"></a>aggregateBykey</h5><h5 id="foldByKey-amp-combinByKey"><a href="#foldByKey-amp-combinByKey" class="headerlink" title="foldByKey &amp; combinByKey"></a>foldByKey &amp; combinByKey</h5><h5 id="sortByKey-amp-mapValueByKey"><a href="#sortByKey-amp-mapValueByKey" class="headerlink" title="sortByKey &amp; mapValueByKey"></a>sortByKey &amp; mapValueByKey</h5><blockquote><p>方法不同，底层实现和代码的执行位置很不同，<br>是的Driver执行还是在Executor执行？</p></blockquote><h3 id="RDD的依赖"><a href="#RDD的依赖" class="headerlink" title="RDD的依赖"></a>RDD的依赖</h3><h4 id="窄依赖"><a href="#窄依赖" class="headerlink" title="窄依赖"></a>窄依赖</h4><p>窄依赖指的是每一个父RDD的Partition最多被子RDD的一个Partition使用，窄依赖被比喻为独生子女。</p><h4 id="宽依赖"><a href="#宽依赖" class="headerlink" title="宽依赖"></a>宽依赖</h4><p>宽依赖指的是每一个父RDD的Partition可以被多个子RDD的Partition使用。</p><h4 id="DAG"><a href="#DAG" class="headerlink" title="DAG"></a>DAG</h4><h4 id="任务划分"><a href="#任务划分" class="headerlink" title="任务划分"></a>任务划分</h4><p>宽依赖放在不同的stage，窄依赖放在同一个stage。</p><ol><li>Application：初始化一个SparkContext即生成一个Application；</li><li>Job：一个Action算子就会生成一个Job；</li><li>Stage：根据RDD依赖关系，将Job划分成不同的Stage，一个宽依赖就划分一个新的Stage；</li><li>Task：Stage是一个TaskSet，将Stage划分的结果发送到不同Executor执行即为一个Task；</li><li>上述四者每一层都是一对n的关系；</li></ol><h3 id="RDD的缓存"><a href="#RDD的缓存" class="headerlink" title="RDD的缓存"></a>RDD的缓存</h3><p>通过persist方法或cache方法可以将前面的计算结果缓存，默认情况下persist()会把数据以序列化的形式缓存在JVM的堆空间中。但是并不是这两个方法调用时立刻缓存，而是触发后面的action时，该RDD将会被缓存在计算节点的内存中，供后面重用。</p><p>此外还有checkpoint功能，通过函数setCheckpointDir(dir)设置。</p><p>一般在血缘关系比较长的时候使用。</p><h3 id="RDD分区器"><a href="#RDD分区器" class="headerlink" title="RDD分区器"></a>RDD分区器</h3><h2 id="Spark三大数据结构"><a href="#Spark三大数据结构" class="headerlink" title="Spark三大数据结构"></a>Spark三大数据结构</h2><ul><li>RDD：分布式数据集</li><li>广播变量：分布式只读共享变量 broadcast，调优策略</li><li>累加器：分布式只写共享变量，LongAccumulator</li></ul><h3 id="Spark中的数量"><a href="#Spark中的数量" class="headerlink" title="Spark中的数量"></a>Spark中的数量</h3><ul><li>Executor：默认有2个；可以通过提交参数设置；</li><li>partition：默认情况，读取文件采用Hadoop的切片规则，如果读取内存中的数据，可以根据特定的算法设定，可以通过其他算子进行改变；多个阶段的场合，下一个阶段分区的数量受到上一个阶段分区的影响；</li><li>Stage：ResultStage + Shuffle依赖的数量，划分阶段的目的就是为了任务执行的等待，因为Shuffle的过程需要落盘；</li><li>Task：原则上一个分区就是一个任务，但实际中，可以动态调整；</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;hadoop历史&quot;&gt;&lt;a href=&quot;#hadoop历史&quot; class=&quot;headerlink&quot; title=&quot;hadoop历史&quot;&gt;&lt;/a&gt;hadoop历史&lt;/h2&gt;&lt;p&gt;2011年发布1.0版本，2012年发布稳定版，2013发布2.x版本（Yarn）&lt;/p&gt;

      
    
    </summary>
    
    
      <category term="spark" scheme="http://zkalan.com/categories/spark/"/>
    
    
      <category term="spark" scheme="http://zkalan.com/tags/spark/"/>
    
  </entry>
  
  <entry>
    <title>javaCV初步使用之rtmp推流和在线播放</title>
    <link href="http://zkalan.com/javaCV%E5%88%9D%E6%AD%A5%E4%BD%BF%E7%94%A8%E4%B9%8Brtmp%E6%8E%A8%E6%B5%81%E5%92%8C%E5%9C%A8%E7%BA%BF%E6%92%AD%E6%94%BE.html"/>
    <id>http://zkalan.com/javaCV%E5%88%9D%E6%AD%A5%E4%BD%BF%E7%94%A8%E4%B9%8Brtmp%E6%8E%A8%E6%B5%81%E5%92%8C%E5%9C%A8%E7%BA%BF%E6%92%AD%E6%94%BE.html</id>
    <published>2019-12-26T06:06:07.000Z</published>
    <updated>2025-06-10T19:14:52.025Z</updated>
    
    <content type="html"><![CDATA[<h2 id="从设备获取视频流"><a href="#从设备获取视频流" class="headerlink" title="从设备获取视频流"></a>从设备获取视频流</h2><blockquote><p>参考链接<br><a href="https://blog.csdn.net/eguid_1/article/details/52678775" target="_blank" rel="noopener">https://blog.csdn.net/eguid_1/article/details/52678775</a></p></blockquote><p>这块内容主要是javaCV基本API的使用，代码非常简单，我将其写在了一个类中，位于<br>src/main/java/com/zkalan/capture下，然后再demo类中调用测试；需要注意的是，网<br>上的很多代码将画板canvas的销毁方式设置为EXIT_ON_CLOSE，这会导致java虚拟机直接<br>推出，资源无法释放。我认为正确的写法应该是DISPOSED_ON_CLOSE。</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">canvas.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);</span><br></pre></td></tr></table></figure><h2 id="搭建rtmp推流服务器"><a href="#搭建rtmp推流服务器" class="headerlink" title="搭建rtmp推流服务器"></a>搭建rtmp推流服务器</h2><p>通过nginx服务器和nginx-rtmp-module可以简单的搭建一个rtmp服务器，我将使用的nginx<br>编译版本放在了<a href="https://download.csdn.net/download/bucuo12345/12054279" target="_blank" rel="noopener">这里</a><br>，这是已经包含了nginx-rtmp-module的版本，使用非常简单，首先在配置文件，例如<br>nginx-win-rtmp.conf中，添加一段rtmp配置项</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><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">rtmp &#123;</span><br><span class="line">    server &#123;</span><br><span class="line">        listen 1935;</span><br><span class="line">        chunk_size 4000;</span><br><span class="line">        #mylive就是直播项目名</span><br><span class="line">        application mylive &#123;</span><br><span class="line">             live on;</span><br><span class="line"> </span><br><span class="line">             # record first 1K of stream</span><br><span class="line">             record all;</span><br><span class="line">             record_path /tmp/av;</span><br><span class="line">             record_max_size 1K;</span><br><span class="line"> </span><br><span class="line">             # append current timestamp to each flv</span><br><span class="line">             record_unique on;</span><br><span class="line"> </span><br><span class="line">             # publish only from localhost</span><br><span class="line">             #allow publish 127.0.0.1;</span><br><span class="line">             #deny publish all;</span><br><span class="line"> </span><br><span class="line">             #allow play all;</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>然后在命令行中启动nginx服务器，例如命令</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">start nginx.exe -c conf\nginx-win-rtmp.conf</span><br></pre></td></tr></table></figure><p>最后，启动第一部分写好的demo程序，注意publish address应该是这样的格式<br>rtmp://localhost:port/mylive/，使用potplayer或者vlc访问该链接，测试推流是否成功。</p><h2 id="在网页播放rtmp流"><a href="#在网页播放rtmp流" class="headerlink" title="在网页播放rtmp流"></a>在网页播放rtmp流</h2><blockquote><p>参考链接<br><a href="https://blog.csdn.net/qq_30152271/article/details/84334734" target="_blank" rel="noopener">https://blog.csdn.net/qq_30152271/article/details/84334734</a></p></blockquote><p>操作起来很简单，就是创建一个静态网页，放到服务器目录下，启动任何一个静态服务器，例如<br>上文的nginx，访问该静态网页，只要地址填写正确，就可以观看推流内容了。</p><font color="#99CC00">然而需要注意的是，videojs虽然声称是一个html5播放器，但它的5.x版本播放rtmp流时依然需要flash支持，并且6.x及以后版本不支持rtmp播放，也许是为了真正的叫做“html5播放器”？</font><h2 id="Demo地址"><a href="#Demo地址" class="headerlink" title="Demo地址"></a>Demo地址</h2><p><a href="https://github.com/zkalan/javaCV-rtmp-demo" target="_blank" rel="noopener">javaCV-rtmp-demo</a></p><p>浏览器效果图</p><p><img src="http://cdn.zkalan.com/1.PNG" alt></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;从设备获取视频流&quot;&gt;&lt;a href=&quot;#从设备获取视频流&quot; class=&quot;headerlink&quot; title=&quot;从设备获取视频流&quot;&gt;&lt;/a&gt;从设备获取视频流&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;参考链接&lt;br&gt;&lt;a href=&quot;https://blog.csd
      
    
    </summary>
    
    
      <category term="javaCV" scheme="http://zkalan.com/categories/javaCV/"/>
    
    
      <category term="rtmp" scheme="http://zkalan.com/tags/rtmp/"/>
    
      <category term="javacv" scheme="http://zkalan.com/tags/javacv/"/>
    
      <category term="nginx" scheme="http://zkalan.com/tags/nginx/"/>
    
  </entry>
  
  <entry>
    <title>Mybatis第一节</title>
    <link href="http://zkalan.com/Mybatis%E7%AC%AC%E4%B8%80%E8%8A%82.html"/>
    <id>http://zkalan.com/Mybatis%E7%AC%AC%E4%B8%80%E8%8A%82.html</id>
    <published>2019-12-16T13:49:09.000Z</published>
    <updated>2025-06-10T19:14:52.024Z</updated>
    
    <content type="html"><![CDATA[<p>持久层技术解决方案有JDBC技术、Sping中对JDBC的简单封装、Apache的DBUtils等，这些都不是框架技术，后两者只是工具类。Mybatis是一个持久层框架，使用ORM思想实现了结果集的封装。ORM就是把数据库表和实体类及其实体类的属性对应起来。</p><h2 id="环境搭建"><a href="#环境搭建" class="headerlink" title="环境搭建"></a>环境搭建</h2><ol><li>创建maven工程并导入坐标；</li><li>创建实体类和dao的接口；</li><li>创建Mybatis的主配置文件SqlMapConfig.xml</li><li>创建映射配置文件；</li></ol><h3 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h3><ol><li>在Mybatis中把持久层的接口名称和映射文件也叫做Mapper；</li><li>Mybatis的映射配置文件位置必须和dao接口的包结构相同；</li><li>映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名；</li><li>映射配置文件的操作配置，id属性的取值必须是dao接口的方法名；</li><li>遵守3、4和5，不需要自己写dao接口实现类；</li></ol><h2 id="Mybatis连接池"><a href="#Mybatis连接池" class="headerlink" title="Mybatis连接池"></a>Mybatis连接池</h2><p>提供了三种配置方式。<br>配置的位置：主配置文件SqlMapConfig.xml中的dataSource标签，type属性就是表示采用哪种连接池。</p><ul><li>POOLED：采用传统的javax.sql.DataSource规范中的连接池，mybatis中有针对规范的实现。</li><li>UNPOOLED：采用传统的获取连接的方式，虽然也实现Javax.sql.DataSource接口，但是并没有使用赤的思想。</li><li>JNDI：采用服务器提供的JNDI技术实现，来获取DataSource对象，不同的服务器能拿到的DataSource不同。web和maven的war工程才可使用。tomcat服务器采用的连接池是dbcp连接池。</li></ul><h2 id="Mybatis中的事务"><a href="#Mybatis中的事务" class="headerlink" title="Mybatis中的事务"></a>Mybatis中的事务</h2><p>通过sqlsession对象的commit方法和rollback方法实现事务的提交和回滚。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;持久层技术解决方案有JDBC技术、Sping中对JDBC的简单封装、Apache的DBUtils等，这些都不是框架技术，后两者只是工具类。Mybatis是一个持久层框架，使用ORM思想实现了结果集的封装。ORM就是把数据库表和实体类及其实体类的属性对应起来。&lt;/p&gt;
&lt;h2
      
    
    </summary>
    
    
      <category term="mybatis" scheme="http://zkalan.com/categories/mybatis/"/>
    
    
      <category term="mybatis" scheme="http://zkalan.com/tags/mybatis/"/>
    
  </entry>
  
  <entry>
    <title>SpringMVC第一节</title>
    <link href="http://zkalan.com/SpringMVC%E7%AC%AC%E4%B8%80%E8%8A%82.html"/>
    <id>http://zkalan.com/SpringMVC%E7%AC%AC%E4%B8%80%E8%8A%82.html</id>
    <published>2019-12-10T09:08:49.000Z</published>
    <updated>2025-06-10T19:14:52.024Z</updated>
    
    <content type="html"><![CDATA[<p>SpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级web框架，属于Spring FrameWork的后续产品，以及融合在Spring Web Flow里面。Spring框架提供了构建Web应用程序的全部功能MVC模块，使用Spring可插入的MVC框架，从而在进行Web开发时，选择使用Spring MVC框架或集成其他MVC开发框架，如Struts2等。支持RESTful编程风格的请求。</p><ul><li>清晰的角色划分；</li><li>分工明确，扩展灵活；</li><li>等</li></ul><h2 id="基本组件"><a href="#基本组件" class="headerlink" title="基本组件"></a>基本组件</h2><h3 id="DispatcherServlet前端控制器"><a href="#DispatcherServlet前端控制器" class="headerlink" title="DispatcherServlet前端控制器"></a>DispatcherServlet前端控制器</h3><p>用户i请求到达前端控制器，相当于MVC模式中的C，DispatcherServlet是整个流程控制的中心，由它调用其他组件处理用户的请求，DispatcherServlet降低了组件之间的耦合。</p><h3 id="HandlerMapping处理器映射器"><a href="#HandlerMapping处理器映射器" class="headerlink" title="HandlerMapping处理器映射器*"></a>HandlerMapping处理器映射器*</h3><p>HandlerMapping负责根据用户请求找到Handler，SpingMVC提供了不同的映射器实现不同的映射方式，例如配置文件方式、实现接口方式、注解方式等。</p><h3 id="Handler处理器"><a href="#Handler处理器" class="headerlink" title="Handler处理器"></a>Handler处理器</h3><p>开发中需要编写的具体业务控制器，由DispatcherServlet把用户的请求转发到Handler，由Handler对具体的用户请求进行处理。</p><h3 id="HandlerAdapter处理器适配器"><a href="#HandlerAdapter处理器适配器" class="headerlink" title="HandlerAdapter处理器适配器*"></a>HandlerAdapter处理器适配器*</h3><p>通过HandlerAdapter对处理器进行执行，这是适配器模式的应用，通过扩展适配器可以对更多类型的处理器进行执行。</p><h3 id="View-Resolver视图解析器"><a href="#View-Resolver视图解析器" class="headerlink" title="View Resolver视图解析器*"></a>View Resolver视图解析器*</h3><p>View Resolver负责将处理结果生成View视图，View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址，再生成View视图对象，最后对View进行渲染将处理结果通过页面展示给用户。</p><h3 id="View视图"><a href="#View视图" class="headerlink" title="View视图"></a>View视图</h3><p>SpringMVC框架提供了很多的View视图类型的支持，包括jstlView, freemarkerView, pdfView等。最常用的是jsp。一般情况下需要通过页面标签或页面模板技术将模型数据通过页面展示给用户。</p><h2 id="RequestMapping"><a href="#RequestMapping" class="headerlink" title="RequestMapping"></a>RequestMapping</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><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="keyword">package</span> org.springframework.web.bind.annotation;</span><br><span class="line"><span class="keyword">import</span> java.lang.annotation.Documented;</span><br><span class="line"><span class="keyword">import</span> java.lang.annotation.ElementType;</span><br><span class="line"><span class="keyword">import</span> java.lang.annotation.Retention;</span><br><span class="line"><span class="keyword">import</span> java.lang.annotation.RetentionPolicy;</span><br><span class="line"><span class="keyword">import</span> java.lang.annotation.Target;</span><br><span class="line"><span class="keyword">import</span> org.springframework.core.annotation.AliasFor;</span><br><span class="line"></span><br><span class="line"><span class="comment">//可以作用于类和方法，支持分级映射</span></span><br><span class="line"><span class="meta">@Target</span>(&#123;ElementType.METHOD, ElementType.TYPE&#125;)</span><br><span class="line"><span class="meta">@Retention</span>(RetentionPolicy.RUNTIME)</span><br><span class="line"><span class="meta">@Documented</span></span><br><span class="line"><span class="meta">@Mapping</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> RequestMapping &#123;</span><br><span class="line"></span><br><span class="line"><span class="function">String <span class="title">name</span><span class="params">()</span> <span class="keyword">default</span> ""</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//别名path和value通用，用于指定url</span></span><br><span class="line"><span class="meta">@AliasFor</span>(<span class="string">"path"</span>)</span><br><span class="line">String[] value() <span class="keyword">default</span> &#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="meta">@AliasFor</span>(<span class="string">"value"</span>)</span><br><span class="line">String[] path() <span class="keyword">default</span> &#123;&#125;;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    <span class="comment">//public enum RequestMethod &#123;</span></span><br><span class="line">    <span class="comment">//GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE</span></span><br><span class="line">    <span class="comment">//&#125;</span></span><br><span class="line">    RequestMethod[] method() <span class="keyword">default</span> &#123;&#125;;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//限定传递的请求参数</span></span><br><span class="line">String[] params() <span class="keyword">default</span> &#123;&#125;;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//用于指定限制请求的头条件</span></span><br><span class="line">String[] headers() <span class="keyword">default</span> &#123;&#125;;</span><br><span class="line"></span><br><span class="line">String[] consumes() <span class="keyword">default</span> &#123;&#125;;</span><br><span class="line"></span><br><span class="line">String[] produces() <span class="keyword">default</span> &#123;&#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="请求参数的绑定"><a href="#请求参数的绑定" class="headerlink" title="请求参数的绑定"></a>请求参数的绑定</h2><p>支持简单数据类型、对象、列表等。@RequestMapping(param={username=””})</p><h2 id="自定义类型转换器"><a href="#自定义类型转换器" class="headerlink" title="自定义类型转换器"></a>自定义类型转换器</h2><ol><li>首先实现Converter接口；</li><li>在spring配置文件中配置自定义类型转换器；</li></ol><h2 id="Servlet原生API"><a href="#Servlet原生API" class="headerlink" title="Servlet原生API"></a>Servlet原生API</h2><p>HttpServletRequest、HttpServletResponse、HttpSession、ServletContext。</p><h2 id="常用注解"><a href="#常用注解" class="headerlink" title="常用注解"></a>常用注解</h2><ol><li>@RequestParam</li><li>@RequestBody get方法不适用</li><li>@PathVariable RESTful风格 WebClient模拟发送请求</li><li>@RequestHeader</li><li>@CookieValue 获取cookie的值</li><li>@ModelAttribute</li><li>@SessionAttributes 用于多次执行控制器方法间的参数共享</li></ol><h2 id="ResponseBody相应json数据"><a href="#ResponseBody相应json数据" class="headerlink" title="ResponseBody相应json数据"></a>ResponseBody相应json数据</h2><p>DispatcherServlet会拦截所有资源，导致静态资源，如image、css、js等也会被拦截，解决方法就是需要配置静态资源不拦截。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;SpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级web框架，属于Spring FrameWork的后续产品，以及融合在Spring Web Flow里面。Spring框架提供了构建Web应用程序的全部功能MVC模块，使用Spring可插入的MV
      
    
    </summary>
    
    
      <category term="SpringMVC" scheme="http://zkalan.com/categories/SpringMVC/"/>
    
    
      <category term="SpringMVC" scheme="http://zkalan.com/tags/SpringMVC/"/>
    
  </entry>
  
  <entry>
    <title>Docker</title>
    <link href="http://zkalan.com/Docker.html"/>
    <id>http://zkalan.com/Docker.html</id>
    <published>2019-12-10T07:18:05.000Z</published>
    <updated>2025-06-10T19:14:52.024Z</updated>
    
    <content type="html"><![CDATA[<p>Docker是一个开源的应用容器引擎；支持将软件编译成一个镜像，然后在镜像中做好各种软件的配置工作，随后将镜像发不出去，其他使用者可以直接使用该镜像；运行中的这个镜像成为容器，其优点在于启动速度。</p><h2 id="Docker核心概念"><a href="#Docker核心概念" class="headerlink" title="Docker核心概念"></a>Docker核心概念</h2><h3 id="Docker主机Host"><a href="#Docker主机Host" class="headerlink" title="Docker主机Host"></a>Docker主机Host</h3><p>一个物理或虚拟的机器，用于执行Docker守护进程和容器；</p><h3 id="Docker镜像Images"><a href="#Docker镜像Images" class="headerlink" title="Docker镜像Images"></a>Docker镜像Images</h3><p>Docker镜像是用于创建Docker容器的模板；</p><h3 id="Docker容器Container"><a href="#Docker容器Container" class="headerlink" title="Docker容器Container"></a>Docker容器Container</h3><p>容器是独立运行的一个或一组应用；</p><h3 id="Docker客户端Client"><a href="#Docker客户端Client" class="headerlink" title="Docker客户端Client"></a>Docker客户端Client</h3><p>客户端通过命令行或者其他工具使用Docker API和Docker的守护进程通信；</p><h3 id="Docker仓库Registry"><a href="#Docker仓库Registry" class="headerlink" title="Docker仓库Registry"></a>Docker仓库Registry</h3><p>Docker仓库用来保存镜像，可以理解为代码控制中的代码仓库，Docker Hub提供了庞大的镜像集合使用；</p><h2 id="使用Docker"><a href="#使用Docker" class="headerlink" title="使用Docker"></a>使用Docker</h2><h3 id="基本命令"><a href="#基本命令" class="headerlink" title="基本命令"></a>基本命令</h3><figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><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">yum install docker</span><br><span class="line">docker -v</span><br><span class="line">systemctl start docker</span><br><span class="line">systemctl enable docker</span><br></pre></td></tr></table></figure><figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><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 search mysql #搜索mysql image</span><br><span class="line">docker pull mysql #拉取镜像</span><br><span class="line">docker images #查看镜像列表</span><br><span class="line">docker rmi images-id #移除镜像</span><br></pre></td></tr></table></figure><h3 id="容器操作"><a href="#容器操作" class="headerlink" title="容器操作"></a>容器操作</h3><figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">docker run --name mymysql -d mysql:TAG #启动容器</span><br><span class="line">docker ps #查看运行中的容器</span><br><span class="line">docker ps -a #查看所有容器</span><br><span class="line">docker stop container-id #停止容器</span><br><span class="line">docker rm -a # 删除所有容器</span><br><span class="line">docker run --name container-name iamge-name -d -p 1008:8080 #-p进行端口映射</span><br><span class="line">docker logs container-id/container-name</span><br></pre></td></tr></table></figure><h3 id="其他命令"><a href="#其他命令" class="headerlink" title="其他命令"></a>其他命令</h3>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;Docker是一个开源的应用容器引擎；支持将软件编译成一个镜像，然后在镜像中做好各种软件的配置工作，随后将镜像发不出去，其他使用者可以直接使用该镜像；运行中的这个镜像成为容器，其优点在于启动速度。&lt;/p&gt;
&lt;h2 id=&quot;Docker核心概念&quot;&gt;&lt;a href=&quot;#Dock
      
    
    </summary>
    
    
      <category term="Docker" scheme="http://zkalan.com/categories/Docker/"/>
    
    
      <category term="Docker" scheme="http://zkalan.com/tags/Docker/"/>
    
  </entry>
  
  <entry>
    <title>spring-boot和web开发</title>
    <link href="http://zkalan.com/spring-boot%E5%92%8Cweb%E5%BC%80%E5%8F%91.html"/>
    <id>http://zkalan.com/spring-boot%E5%92%8Cweb%E5%BC%80%E5%8F%91.html</id>
    <published>2019-12-06T13:33:07.000Z</published>
    <updated>2025-06-10T19:14:52.025Z</updated>
    
    <content type="html"><![CDATA[<h2 id="web开发"><a href="#web开发" class="headerlink" title="web开发"></a>web开发</h2><p>如何使用spring boot：</p><ol><li>创建spring boot应用，选中需要的模块；</li><li>spring boot已经默认将这些场景配置好，只需要在配置文件中指定少量配置就可与运行；</li><li>编写业务代码；</li></ol><p><em>自动配置原理</em></p><h2 id="webjars和静态资源映射规则"><a href="#webjars和静态资源映射规则" class="headerlink" title="webjars和静态资源映射规则"></a>webjars和静态资源映射规则</h2><ol><li><p>所有/webjars/**，都去classpath:/META-INF/resources/webjars查找资源；<br>webjars：以jar包方式引入静态资源。</p></li><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></pre></td><td class="code"><pre><span class="line">"classpath:/MEAT-INF/resources/",</span><br><span class="line">"classpath:/resources/",</span><br><span class="line">"calsspath:/static/",</span><br><span class="line">"calsspath:/puclic/",</span><br><span class="line">"/":当前目录的根目录</span><br></pre></td></tr></table></figure></li><li><p>欢迎页：静态资源文件夹下的所有index.html页面，被”/**”映射；</p></li><li><p>所有的**/favicon.ico都是在静态资源文件夹下查找；</p></li></ol><h2 id="模板引擎"><a href="#模板引擎" class="headerlink" title="模板引擎"></a>模板引擎</h2><p>JSP、</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">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-thymeleaf<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">properties</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">thymeleaf.version</span>&gt;</span>3.0.9.RELEASE<span class="tag">&lt;/<span class="name">thymeleaf.version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">thymeleaf-layout-dialect.version</span>&gt;</span>2.3.0<span class="tag">&lt;/<span class="name">thymeleaf-layout-dialect.version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">properties</span>&gt;</span></span><br></pre></td></tr></table></figure><h3 id="thymeleaf"><a href="#thymeleaf" class="headerlink" title="thymeleaf"></a>thymeleaf</h3><h4 id="导入语法空间"><a href="#导入语法空间" class="headerlink" title="导入语法空间"></a>导入语法空间</h4><h4 id="thymeleaf语法规则"><a href="#thymeleaf语法规则" class="headerlink" title="thymeleaf语法规则"></a>thymeleaf语法规则</h4><ul><li>片段包含：jsp:include<ul><li>th:insert</li><li>th:replace</li></ul></li><li>遍历:c:forEach<ul><li>th:each</li></ul></li><li>条件判断c:if<ul><li>th:if</li><li>th:unless</li><li>th:switch</li><li>th:case</li></ul></li><li>声明变量c:set<ul><li>th:object</li><li>th:with</li></ul></li><li>任意属性修改支持prepend,append<ul><li>th:attr</li><li>th:attrprepend</li><li>th:attrappend</li></ul></li><li>修改指定属性默认值<ul><li>th:value</li><li>th:href</li><li>th:src</li></ul></li><li>修改标签体内容<ul><li>th:text不转义</li><li>th:utext转义</li></ul></li><li>声明片段<ul><li>th:fragment</li></ul></li><li>…</li></ul><h4 id="thymeleaf表达式"><a href="#thymeleaf表达式" class="headerlink" title="thymeleaf表达式"></a>thymeleaf表达式</h4><ul><li>Simple expressions:<ul><li>Variable Expressions: ${…}</li><li>Selection Variable Expressions: *{…}</li><li>Message Expressions: #{…}</li><li>Link URL Expressions: @{…}</li><li>Fragment Expressions: ~{…}</li></ul></li><li>Literals<ul><li>Text literals: ‘one text’ , ‘Another one!’ ,…</li><li>Number literals: 0 , 34 , 3.0 , 12.3 ,…</li><li>Boolean literals: true , false</li><li>Null literal: null</li><li>Literal tokens: one , sometext , main ,…</li></ul></li><li>Text operations:<ul><li>String concatenation: +</li><li>Literal substitutions: |The name is ${name}|</li></ul></li><li>Arithmetic operations:<ul><li>Binary operators: + , - , * , / , %</li><li>Minus sign (unary operator): -</li></ul></li><li>Boolean operations:<ul><li>Binary operators: and , or</li><li>Boolean negation (unary operator): ! , not</li></ul></li><li>Comparisons and equality:<ul><li>Comparators: &gt; , &lt; , &gt;= , &lt;= ( gt , lt , ge , le )</li><li>Equality operators: == , != ( eq , ne )</li></ul></li><li>Conditional operators:<ul><li>If-then: (if) ? (then)</li><li>If-then-else: (if) ? (then) : (else)</li><li>Default: (value) ?: (defaultvalue)</li></ul></li><li>Special tokens:<ul><li>No-Operation: _</li></ul></li></ul><h2 id="Spring-Boot自动配置Spring-MVC"><a href="#Spring-Boot自动配置Spring-MVC" class="headerlink" title="Spring Boot自动配置Spring MVC"></a>Spring Boot自动配置Spring MVC</h2><ul><li>Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans;</li><li>Support for serving static resourcces, including support for Webjars;</li><li>Automatic registration of Converter, GenericConverter, Formatter beans;</li><li>Support for HttpMessageConerters;</li><li>Automatic registration of MessageCodeResolver;</li><li>Static index.html support;</li><li>Custom Favicon support;</li><li>Automatic use of a ConfigurableWebBindingInitializer bean;</li></ul><h3 id="修改Spring-Boot默认配置"><a href="#修改Spring-Boot默认配置" class="headerlink" title="修改Spring Boot默认配置"></a>修改Spring Boot默认配置</h3><h3 id="扩展Spring-MVC"><a href="#扩展Spring-MVC" class="headerlink" title="扩展Spring MVC"></a>扩展Spring MVC</h3><h2 id="Tips"><a href="#Tips" class="headerlink" title="Tips"></a>Tips</h2><h3 id="国际化"><a href="#国际化" class="headerlink" title="国际化"></a>国际化</h3><p>默认的区域信息是通过浏览器请求报文获取的。可以通过链接提交区域信息。<br>自己的信息解析器需要实现Localeresolver。</p><ol><li>编写国际化配置文件，抽取页面需要配置的国际化信息；</li><li>使用ResourceBundleMessageSource管理国际化资源信息；</li><li>在页面使用fml:message获取国际化内容；</li><li>可以自己编写区域信息解析器，替换Spring Boot默认的解析器ResourceBundleMessageSource；</li></ol><p><strong>模板引擎要实时生效，需要禁用模板缓存，页面修改要ctrl+F9重新编译</strong></p><h3 id="登陆状态检查需要拦截器"><a href="#登陆状态检查需要拦截器" class="headerlink" title="登陆状态检查需要拦截器"></a>登陆状态检查需要拦截器</h3><h3 id="thymeleaf公共页面元素抽取"><a href="#thymeleaf公共页面元素抽取" class="headerlink" title="thymeleaf公共页面元素抽取"></a>thymeleaf公共页面元素抽取</h3><ol><li>抽取公共片段<div th:fragment="copy"></div></li><li>引入公共片段<div th:insert="~{footer::copy}"></div></li><li>不同替换效果有th:insert、th:replace、th:include</li></ol><h3 id="错误处理的自动配置"><a href="#错误处理的自动配置" class="headerlink" title="错误处理的自动配置"></a>错误处理的自动配置</h3><p>可以参照ErrorMVCAutoConfiguration；容器中有如下组件：</p><ol><li>DefaultErrorAttributes</li><li>BasicErrorController</li><li>ErrorPageCustomizer</li><li>DefaultErrorViewResolver</li></ol><h2 id="注册Servlet、Filter、Linstener"><a href="#注册Servlet、Filter、Linstener" class="headerlink" title="注册Servlet、Filter、Linstener"></a>注册Servlet、Filter、Linstener</h2><p>Spring Boot默认是以jar包的方式启动嵌入式的Servlet容器来启动Spring Boot的web应用，没有web.xml文件；<br>注册三大组件使用ServletRegistrationBean, FilterRegistrationBean, ServletListenerRegistrationBean。</p><h3 id="其他嵌入式Servlet容器"><a href="#其他嵌入式Servlet容器" class="headerlink" title="其他嵌入式Servlet容器"></a>其他嵌入式Servlet容器</h3><h4 id="Jetty"><a href="#Jetty" class="headerlink" title="Jetty"></a>Jetty</h4><p>适合长连接</p><h4 id="Undertow"><a href="#Undertow" class="headerlink" title="Undertow"></a>Undertow</h4><p>后置处理器会获取所有容器中的定制器，以此配置Servlet容器，自己定义容器就是将自定义的定制器加到Bean工厂中。</p><h2 id="嵌入式Servlet容器启动原理"><a href="#嵌入式Servlet容器启动原理" class="headerlink" title="嵌入式Servlet容器启动原理"></a>嵌入式Servlet容器启动原理</h2><ol><li>Spring Boot应用启动运行run方法；</li><li>refreshContext(context);Spring Boot刷新IOC容器，创建IOC容器对象，并初始化容器，创建容器中的每一个组件，还判断了是否是web应用；</li><li>refresh(context);刷新刚才创建好的ioc容器；</li><li>onRefresh();web的IOC容器重写了onRefresh方法；</li><li>web IOC容器会创建嵌入式的Servlet容器；createEmbeddedServletContainer();</li><li>获取嵌入式的Servlet容器工厂；TomcatEmbeddedServletContainerFactory创建对象，后置处理器随后获取所有的定制器来定制Servlet容器的相关配置；</li><li>使用容器工厂获取嵌入式的Servlet容器；</li><li>嵌入式的Servlet容器创建对象并启动Servlet容器；先启动嵌入式的Servlet容器，再将IOC容器中剩下的对象获取；</li></ol><h2 id="使用外置的Servlet容器"><a href="#使用外置的Servlet容器" class="headerlink" title="使用外置的Servlet容器"></a>使用外置的Servlet容器</h2><p>嵌入式Servlet容器优点在于简单、便携，缺点在于默认不支持JSP，优化定制不够复杂；使用定制器、自己编写嵌入式Servlet容器的创建工厂；</p><ol><li>必须创建一个war项目，利用idea创建目录结构；</li><li>将嵌入式的Tomcat指定为provided；</li><li>必须编写一个SpringBootServletInitializer的子类，并调用configure方法；</li><li>启动tomcat；</li></ol>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;web开发&quot;&gt;&lt;a href=&quot;#web开发&quot; class=&quot;headerlink&quot; title=&quot;web开发&quot;&gt;&lt;/a&gt;web开发&lt;/h2&gt;&lt;p&gt;如何使用spring boot：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;创建spring boot应用，选中需要的模块；&lt;/li
      
    
    </summary>
    
    
      <category term="spring-boot" scheme="http://zkalan.com/categories/spring-boot/"/>
    
    
      <category term="spring-boot" scheme="http://zkalan.com/tags/spring-boot/"/>
    
      <category term="web开发" scheme="http://zkalan.com/tags/web%E5%BC%80%E5%8F%91/"/>
    
  </entry>
  
  <entry>
    <title>YAML</title>
    <link href="http://zkalan.com/YAML.html"/>
    <id>http://zkalan.com/YAML.html</id>
    <published>2019-12-05T12:23:40.000Z</published>
    <updated>2025-06-10T19:14:52.024Z</updated>
    
    <content type="html"><![CDATA[<ol><li><strong>YAML Ain’t Markup Language</strong></li><li><strong>YAML A Markup Language</strong></li></ol><p>.yml是YAML语言的文件，以数据为中心，比json、xml更适合做配置文件。</p><p>参考语法规范<a href="http://www.yaml.org" target="_blank" rel="noopener">http://www.yaml.org</a></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">server:</span></span><br><span class="line"><span class="attr">    port:</span> <span class="number">8081</span></span><br></pre></td></tr></table></figure><h2 id="基本语法"><a href="#基本语法" class="headerlink" title="基本语法"></a>基本语法</h2><p>key:(空格)value：表示一对键值对，空格是必须的；</p><p>以空格的缩进来控制层级关系，只要左对齐，就认为是同一层级。</p><h2 id="值的写法"><a href="#值的写法" class="headerlink" title="值的写法"></a>值的写法</h2><h3 id="字面值（普通的值，数字、字符串、布尔）"><a href="#字面值（普通的值，数字、字符串、布尔）" class="headerlink" title="字面值（普通的值，数字、字符串、布尔）"></a>字面值（普通的值，数字、字符串、布尔）</h3><p>key:(空格)value：字面直接写</p><ul><li>字符串默认不用引号</li><li>双引号和单引号有区别，前者会对特殊字符转义，后者只会当作普通字符</li></ul><h3 id="数组（list、set）"><a href="#数组（list、set）" class="headerlink" title="数组（list、set）"></a>数组（list、set）</h3><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></pre></td><td class="code"><pre><span class="line"><span class="attr">pets:</span></span><br><span class="line"><span class="bullet"> -</span> <span class="string">cat</span></span><br><span class="line"><span class="bullet"> -</span> <span class="string">dog</span></span><br><span class="line"><span class="bullet"> -</span> <span class="string">pig</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></pre></td><td class="code"><pre><span class="line"><span class="attr">pets:</span> <span class="string">[cat,dog,pig]</span></span><br></pre></td></tr></table></figure><h3 id="对象、Map（属性和值）"><a href="#对象、Map（属性和值）" class="headerlink" title="对象、Map（属性和值）"></a>对象、Map（属性和值）</h3><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></pre></td><td class="code"><pre><span class="line"><span class="attr">friend:</span></span><br><span class="line"><span class="attr">    firstname:</span> <span class="string">zhang</span></span><br><span class="line">    <span class="string">lastname：</span> <span class="string">san</span></span><br><span class="line"><span class="attr">    telphone:</span> <span class="number">136545646</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></pre></td><td class="code"><pre><span class="line"><span class="attr">friend:</span> <span class="string">&#123;firstname:</span> <span class="string">zhang,lastname：</span> <span class="string">san,telphone:</span> <span class="number">136545646</span><span class="string">&#125;</span></span><br></pre></td></tr></table></figure><h2 id="解析yml配置文件"><a href="#解析yml配置文件" class="headerlink" title="解析yml配置文件"></a>解析yml配置文件</h2><p>spring-boot解析yml文件需要使用注解@ConfigurationProperties(prefix = “index-id””)</p><h3 id="ConfigurationProperties和value有区别"><a href="#ConfigurationProperties和value有区别" class="headerlink" title="ConfigurationProperties和value有区别"></a>ConfigurationProperties和value有区别</h3><p>默认从全局配置文件中获取值</p><h2 id="PropertySource"><a href="#PropertySource" class="headerlink" title="@PropertySource"></a>@PropertySource</h2><p>解析非全局配置文件</p><p>@PropertySource(value = “calsspath:example.properties”)</p><h2 id="ImportResource"><a href="#ImportResource" class="headerlink" title="@ImportResource"></a>@ImportResource</h2><p>@ImportResource导入spring配置文件，使配置文件内容生效。</p><p>@ImportResource(location = “classpath:beans.xml”)</p><p>springboot推荐的像容器中添加组件的方式：<br>使用全注解的方式。<br>使用@Configuration指明一个配置类。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;ol&gt;
&lt;li&gt;&lt;strong&gt;YAML Ain’t Markup Language&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;YAML A Markup Language&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;.yml是YAML语言的文件，以数据为中心，比j
      
    
    </summary>
    
    
      <category term="spring-boot" scheme="http://zkalan.com/categories/spring-boot/"/>
    
    
      <category term="spring-boot" scheme="http://zkalan.com/tags/spring-boot/"/>
    
      <category term="yaml" scheme="http://zkalan.com/tags/yaml/"/>
    
  </entry>
  
  <entry>
    <title>gradle</title>
    <link href="http://zkalan.com/gradle.html"/>
    <id>http://zkalan.com/gradle.html</id>
    <published>2019-12-03T08:59:57.000Z</published>
    <updated>2025-06-10T19:14:52.025Z</updated>
    
    <content type="html"><![CDATA[<p>基于JVM的构建工具，有一些特性</p><ul><li>和maven一样基于约定优于配置的构建框架</li><li>强大的多工程构建支持</li><li>强大的依赖管理，基于apachelvy</li><li>支持已有的maven和ivy仓库</li><li>支持传递性依赖管理，不需要远程仓库或pom.xml等配置文件</li></ul><h2 id="gradle安装"><a href="#gradle安装" class="headerlink" title="gradle安装"></a>gradle安装</h2><h3 id="先决条件"><a href="#先决条件" class="headerlink" title="先决条件"></a>先决条件</h3><ul><li>gradle需要1.5或更高版本的JDK；</li><li>gradle自带groovy库，忽略已安装grooy</li></ul><h3 id="配置环境变量"><a href="#配置环境变量" class="headerlink" title="配置环境变量"></a>配置环境变量</h3><ul><li>将GRADLE_HOME/bin添加到PATH变量中</li><li>使用命令gradle -v命令测试</li></ul><h2 id="构建基础"><a href="#构建基础" class="headerlink" title="构建基础"></a>构建基础</h2><h3 id="task"><a href="#task" class="headerlink" title="task"></a>task</h3><h3 id="project"><a href="#project" class="headerlink" title="project"></a>project</h3><h2 id="groovy中的闭包"><a href="#groovy中的闭包" class="headerlink" title="groovy中的闭包"></a>groovy中的闭包</h2><p>就是一段代码块，在gradle中，主要将闭包作为参数使用。</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><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="keyword">def</span> bb = &#123;</span><br><span class="line">    println <span class="string">"hello, bb"</span> </span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//定义一个方法，方法的参数是闭包类型</span></span><br><span class="line"><span class="keyword">def</span> method(Closure closure)&#123;</span><br><span class="line">    closure()</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//调用该方法</span></span><br><span class="line">method(bb)</span><br><span class="line"></span><br><span class="line"><span class="comment">//定义一个闭包，带参数</span></span><br><span class="line"><span class="keyword">def</span> closure2 = &#123;</span><br><span class="line">    v -&gt; println <span class="string">"hello, $&#123;v&#125;"</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">def</span> method2(Closure closure)&#123;</span><br><span class="line">    closure(<span class="string">"world"</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">method2(closure2)</span><br></pre></td></tr></table></figure><h2 id="拆分"><a href="#拆分" class="headerlink" title="拆分"></a>拆分</h2><h2 id="聚合"><a href="#聚合" class="headerlink" title="聚合"></a>聚合</h2><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></pre></td><td class="code"><pre><span class="line">allproject&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;基于JVM的构建工具，有一些特性&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;和maven一样基于约定优于配置的构建框架&lt;/li&gt;
&lt;li&gt;强大的多工程构建支持&lt;/li&gt;
&lt;li&gt;强大的依赖管理，基于apachelvy&lt;/li&gt;
&lt;li&gt;支持已有的maven和ivy仓库&lt;/li&gt;
&lt;li&gt;支
      
    
    </summary>
    
    
      <category term="gradle" scheme="http://zkalan.com/categories/gradle/"/>
    
    
      <category term="gradle" scheme="http://zkalan.com/tags/gradle/"/>
    
  </entry>
  
  <entry>
    <title>maven</title>
    <link href="http://zkalan.com/maven.html"/>
    <id>http://zkalan.com/maven.html</id>
    <published>2019-12-02T13:28:29.000Z</published>
    <updated>2025-06-10T19:14:52.025Z</updated>
    
    <content type="html"><![CDATA[<h2 id="目前存在的问题"><a href="#目前存在的问题" class="headerlink" title="目前存在的问题"></a>目前存在的问题</h2><ol><li>一个项目就是一个工程<br>如果项目非常庞大，就不适用package来划分模块，最好每一个模块对应一个工程，利于分工协作。借助于maven就可以将一个项目拆分为多个工程。</li><li>项目中需要的jar包需要手动管理<br>同样的文件出现在不同的工程中，浪费存储，让文件结构冗余。</li><li>jar包来源复杂，难以维护</li><li>jar包依赖的其他文件仍需手动管理</li></ol><h2 id="什么是maven"><a href="#什么是maven" class="headerlink" title="什么是maven"></a>什么是maven</h2><p>是一款服务于java平台的自动化构建工具。</p><h2 id="什么是构建"><a href="#什么是构建" class="headerlink" title="什么是构建"></a>什么是构建</h2><p>以“java源文件”、“框架配置文件”、JSP、HTML、图片等资源为原材料产生一个可运行的项目的过程。</p><ul><li>清理：将之前编译生成的字节码文件删除，为下一次编译做准备</li><li>编译：将java源程序编程为class字节码文件</li><li>测试：自动测试，自动调用junit程序</li><li>报告：测试程序执行的结果</li><li>打包：动态web工程war包，java工程jar包</li><li>安装：maven特定的概念，将打包得到的文件复制到仓库中指定位置</li><li>部署：将动态web工程生成的war包复制到servlet容器的指定目录下</li></ul><h2 id="安装maven核心程序"><a href="#安装maven核心程序" class="headerlink" title="安装maven核心程序"></a>安装maven核心程序</h2><ul><li><strong>检查JAVA_HOME环境变量</strong></li><li>解压maven核心程序压缩包，英文无空格目录</li><li>配置maven相关环境变量<ul><li>MAVEN_HOME或M2_HOME（bin目录上一级）</li><li>path（通常带bin目录）</li></ul></li><li>运行mvn -v验证配置</li></ul><h2 id="maven核心概念"><a href="#maven核心概念" class="headerlink" title="maven核心概念"></a>maven核心概念</h2><h3 id="约定的目录"><a href="#约定的目录" class="headerlink" title="约定的目录"></a>约定的目录</h3><ul><li>根目录：工程名<ul><li>以配置的方式告诉框架自定义文件：<param-value>classpath:spring-content.xml</param-value></li></ul></li><li>src目录：存放源码</li><li>pom.xml：maven工程核心配置文件</li><li>main目录：存放主程序</li><li>test目录：存放测试程序</li><li>java目录：存放java源码</li><li>resources目录：存放框架或其他工具的配置文件</li></ul><p><em>约定大于配置，配置大于编码</em></p><h3 id="POM"><a href="#POM" class="headerlink" title="POM"></a>POM</h3><p>含义：project object model项目对象模型</p><h3 id="坐标（gav）"><a href="#坐标（gav）" class="headerlink" title="坐标（gav）"></a>坐标（gav）</h3><ul><li>groupid：公司组织域名倒序+项目名</li><li>artifactid：模块名</li><li>version：版本</li></ul><h3 id="依赖"><a href="#依赖" class="headerlink" title="依赖"></a>依赖</h3><ul><li>对于自己的maven工程，使用install命令将其安装到仓库。</li><li>依赖的范围<ul><li>compile：对主程序有效，对测试程序有效，参与打包</li><li>test：对主程序无效，对测试程序有效，不参与打包</li><li>provided：对主程序有效，对测试程序有效，不参与打包，不参与部署，例如servlet-api.jar</li></ul></li><li>scope</li><li>只有compile范围的依赖可以传递</li><li>exclusions用于排除依赖</li></ul><p>依赖的原则</p><ul><li>作用：解决模块工程之间的jar包冲突<ul><li>最短路路径优先</li><li>路径相同时先声明者优先，指的是dependency标签的声明顺序</li></ul></li></ul><p>统一管理依赖的版本号</p><ul><li>properties标签，后跟依赖的id</li><li>通过${依赖的id}访问版本号</li><li>由于test范围的依赖不能传递，所以必然分散在各个模块工程中，导致不一致问题<ul><li>解决思路：将依赖统一提取到父工程中，在子工程中声明依赖时不指定版本，以父工程中统一的设定为准，方便维护</li></ul><ol><li>创建一个maven工程为父工程，注意打包方式为pom</li><li>在子工程中声明对父工程的引用</li><li>将子工程中的坐标中与父工程坐标中重复的内容删除</li><li>在父工程中统一管理依赖</li><li>子工程中删除依赖的版本号</li></ol></li></ul><p><strong>子工程要首先install父工程</strong></p><h3 id="仓库"><a href="#仓库" class="headerlink" title="仓库"></a>仓库</h3><h3 id="生命周期-插件-目标"><a href="#生命周期-插件-目标" class="headerlink" title="生命周期/插件/目标"></a>生命周期/插件/目标</h3><ul><li>各个构建环节执行的顺序是既定的；</li><li>maven核心程序中定义了抽象的生命周期；</li><li>不论执行哪个命令，maven都会从生命周期最开始的位置执行；</li></ul><h3 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h3><h3 id="聚合"><a href="#聚合" class="headerlink" title="聚合"></a>聚合</h3><p><em>一键安装各个模块工程</em><br>在一个总的聚合工程中配置各个参与聚合的模块</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">modules</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">module</span>&gt;</span><span class="tag">&lt;/<span class="name">module</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">module</span>&gt;</span><span class="tag">&lt;/<span class="name">module</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">module</span>&gt;</span><span class="tag">&lt;/<span class="name">module</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">modules</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="常用maven命令"><a href="#常用maven命令" class="headerlink" title="常用maven命令"></a>常用maven命令</h2><p><em>首先进入pom.xml目录</em></p><ul><li>mvn clean：清理</li><li>mvn compile：编译主程序</li><li>mvn test-compile：编译测试程序</li><li>mvn test：执行测试</li><li>mvn package：打包</li><li>mvn install：安装</li><li>mvn site：生成站点</li></ul><h2 id="自动部署"><a href="#自动部署" class="headerlink" title="自动部署"></a>自动部署</h2><p>通过build标签配置当前工程的构建过程中的特殊设置，cargo插件。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;目前存在的问题&quot;&gt;&lt;a href=&quot;#目前存在的问题&quot; class=&quot;headerlink&quot; title=&quot;目前存在的问题&quot;&gt;&lt;/a&gt;目前存在的问题&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;一个项目就是一个工程&lt;br&gt;如果项目非常庞大，就不适用package来划分模块，最好每一
      
    
    </summary>
    
    
      <category term="spring-boot" scheme="http://zkalan.com/categories/spring-boot/"/>
    
    
      <category term="spring-boot" scheme="http://zkalan.com/tags/spring-boot/"/>
    
      <category term="入门" scheme="http://zkalan.com/tags/%E5%85%A5%E9%97%A8/"/>
    
  </entry>
  
  <entry>
    <title>spring boot入门</title>
    <link href="http://zkalan.com/spring-boot%E5%85%A5%E9%97%A8.html"/>
    <id>http://zkalan.com/spring-boot%E5%85%A5%E9%97%A8.html</id>
    <published>2019-12-02T09:08:16.000Z</published>
    <updated>2025-06-10T19:14:52.025Z</updated>
    
    <content type="html"><![CDATA[<h2 id="spring简介"><a href="#spring简介" class="headerlink" title="spring简介"></a>spring简介</h2><p>简化spring开发流程，J2EE开发的一站式解决方案。</p><h3 id="优点"><a href="#优点" class="headerlink" title="优点"></a>优点</h3><ul><li>快速创建独立运行spring项目以及与主流框架集成</li><li>使用嵌入式servlet容器，应用无需达成war包</li><li>starters自动依赖与版本控制</li><li>大量的自动配置，简化开发，也可以修改默认值</li><li>无需配置XML，无代码生成</li><li>准生产环境的运行时应用监控</li><li>与云计算天然集成</li></ul><h2 id="微服务"><a href="#微服务" class="headerlink" title="微服务"></a>微服务</h2><p>是一种架构风格，其认为一个应用应该是一组小型服务，可以用过HTTP的方式通信。</p><p>每一个功能元素最终都是一个可独立替换和独立升级的软件单元。</p><h2 id="环境配置"><a href="#环境配置" class="headerlink" title="环境配置"></a>环境配置</h2><h2 id="spring-boot-starter"><a href="#spring-boot-starter" class="headerlink" title="spring-boot-starter"></a>spring-boot-starter</h2><p>启动器，spring-boot官方提供了一系列启动器。将所有的功能场景抽取出来，只要在项目里面引入这些starter，相关依赖就会自动导入。</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><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 class="doctag">@SpringBootApplication</span>标注这是spring boot应用</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HelloWorldMainApplication</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">        <span class="comment">//spring应用启动</span></span><br><span class="line">        SpringApplication.run(HelloWorldMainApplication.class, args);</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">@Target</span>(&#123;ElementType.TYPE&#125;)</span><br><span class="line"><span class="meta">@Retention</span>(RetentionPolicy.RUNTIME)</span><br><span class="line"><span class="meta">@Documented</span></span><br><span class="line"><span class="meta">@Inherited</span></span><br><span class="line"><span class="meta">@SpringBootConfiguration</span><span class="comment">//表示这是一个Spring Boot的配置类</span></span><br><span class="line"><span class="meta">@EnableAutoConfiguration</span><span class="comment">//开启自动配置功能</span></span><br><span class="line"><span class="meta">@ComponentScan</span>(</span><br><span class="line">    excludeFilters = &#123;<span class="meta">@Filter</span>(</span><br><span class="line">    type = FilterType.CUSTOM,</span><br><span class="line">    classes = &#123;TypeExcludeFilter.class&#125;</span><br><span class="line">), <span class="meta">@Filter</span>(</span><br><span class="line">    type = FilterType.CUSTOM,</span><br><span class="line">    classes = &#123;AutoConfigurationExcludeFilter.class&#125;</span><br><span class="line">)&#125;</span><br><span class="line">)</span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> SpringBootApplication</span><br></pre></td></tr></table></figure><p>@SpringBootConfiguration:表示这是一个Spring Boot的配置类；<br>@Configuration：配置类上，表示配置类也是容器中的一个组件@Component</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">@AutoConfigurationPackage</span><span class="comment">//自动配置包</span></span><br><span class="line"><span class="meta">@Import</span>(EnableAutoConfigurationImportSelector.class)</span><br></pre></td></tr></table></figure><p>spring-boot的注释没事可以看看。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;spring简介&quot;&gt;&lt;a href=&quot;#spring简介&quot; class=&quot;headerlink&quot; title=&quot;spring简介&quot;&gt;&lt;/a&gt;spring简介&lt;/h2&gt;&lt;p&gt;简化spring开发流程，J2EE开发的一站式解决方案。&lt;/p&gt;
&lt;h3 id=&quot;优点&quot;&gt;&lt;
      
    
    </summary>
    
    
      <category term="spring-boot" scheme="http://zkalan.com/categories/spring-boot/"/>
    
    
      <category term="spring-boot" scheme="http://zkalan.com/tags/spring-boot/"/>
    
      <category term="入门" scheme="http://zkalan.com/tags/%E5%85%A5%E9%97%A8/"/>
    
  </entry>
  
  <entry>
    <title>spring的声明式事务控制</title>
    <link href="http://zkalan.com/spring%E7%9A%84%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1%E6%8E%A7%E5%88%B6.html"/>
    <id>http://zkalan.com/spring%E7%9A%84%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1%E6%8E%A7%E5%88%B6.html</id>
    <published>2019-11-15T12:18:11.000Z</published>
    <updated>2025-06-10T19:14:52.026Z</updated>
    
    <content type="html"><![CDATA[<h2 id="基于XML的声明式事务控制"><a href="#基于XML的声明式事务控制" class="headerlink" title="基于XML的声明式事务控制"></a>基于XML的声明式事务控制</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><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><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">&lt;!--配置步骤--&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">bean</span> <span class="attr">id</span>=<span class="string">"tansactionManager"</span> <span class="attr">class</span>=<span class="string">"org.springframework.jdbc.datasource.DataSourceTransactionManager"</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">"dataSource"</span> <span class="attr">ref</span>=<span class="string">"dataSource"</span>&gt;</span><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 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">"txAdvice"</span> <span class="attr">transaction-manager</span>=<span class="string">"transactionManger"</span>&gt;</span><span class="tag">&lt;/<span class="name">tx:advice</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--配置事务的属性</span></span><br><span class="line"><span class="comment">        isolation：用于指定事务的隔离等级，默认是DEFAULT，表示使用数据库的默认隔离等级；</span></span><br><span class="line"><span class="comment">        propagation：用于指定事务的</span></span><br><span class="line"><span class="comment">    --&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">"*"</span> <span class="attr">propagation</span>=<span class="string">"REQUIRED"</span> <span class="attr">read-only</span>=<span class="string">"false"</span>/&gt;</span><span class="tag">&lt;/<span class="name">tx:method</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">"find*"</span> <span class="attr">propagation</span>=<span class="string">"SUPPORTS"</span> <span class="attr">read-only</span>=<span class="string">"true"</span>/&gt;</span><span class="tag">&lt;/<span class="name">tx:method</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 class="comment">&lt;!--配置AOP--&gt;</span></span><br><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="comment">&lt;!--配置事务的属性，在事物的通知tx:advice标签内--&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="comment">&lt;!--配置切入点表达式--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">aop:pointcout</span> <span class="attr">id</span>=<span class="string">"pt1"</span> <span class="attr">execution</span>(* <span class="attr">com.service.impl.</span>*<span class="attr">.</span>*(<span class="attr">..</span>))"&gt;</span><span class="tag">&lt;/<span class="name">aop:pointcut</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">aop:advisor</span> <span class="attr">advice-ref</span>=<span class="string">"txAdvice"</span> <span class="attr">pointcut-ref</span>=<span class="string">"pt1"</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:advisor</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><h2 id="基于纯注解的声明式事务控制"><a href="#基于纯注解的声明式事务控制" class="headerlink" title="基于纯注解的声明式事务控制"></a>基于纯注解的声明式事务控制</h2><ol><li>配置事务管理器；</li><li>开启spring对注解事务的支持；<ul><li>&lt;tx:annotation-driven transaction-manager=”transactionManager”&gt;</li></ul></li><li>在需要事物支持的地方使用@Transactional</li></ol><h2 id="基于编程式事务控制"><a href="#基于编程式事务控制" class="headerlink" title="基于编程式事务控制"></a>基于编程式事务控制</h2><p>不够灵活</p><h2 id="spring5新特性"><a href="#spring5新特性" class="headerlink" title="spring5新特性"></a>spring5新特性</h2><ul><li>与JDK相关升级；</li><li>核心容器更新；</li><li>JetBrains Kotlin语言支持；<ul><li>运行于在JVM上，独立语言；</li></ul></li><li>响应式编程风格；</li><li>Junit5支持；</li><li>依赖类库的更新；</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;基于XML的声明式事务控制&quot;&gt;&lt;a href=&quot;#基于XML的声明式事务控制&quot; class=&quot;headerlink&quot; title=&quot;基于XML的声明式事务控制&quot;&gt;&lt;/a&gt;基于XML的声明式事务控制&lt;/h2&gt;&lt;figure class=&quot;highlight xml&quot;
      
    
    </summary>
    
    
      <category term="Spring" scheme="http://zkalan.com/categories/Spring/"/>
    
    
      <category term="spring" scheme="http://zkalan.com/tags/spring/"/>
    
      <category term="声明式事务控制" scheme="http://zkalan.com/tags/%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1%E6%8E%A7%E5%88%B6/"/>
    
  </entry>
  
  <entry>
    <title>spring中的JdbctTemplate</title>
    <link href="http://zkalan.com/spring%E4%B8%AD%E7%9A%84JdbctTemplate.html"/>
    <id>http://zkalan.com/spring%E4%B8%AD%E7%9A%84JdbctTemplate.html</id>
    <published>2019-11-14T12:50:49.000Z</published>
    <updated>2025-06-10T19:14:52.025Z</updated>
    
    <content type="html"><![CDATA[<p><strong>是spring框架中提供的一个对象，是对原始Jdbc API对象的简单封装，spring框架提供了许多操作模板类。</strong></p><ul><li>操作关系型数据<ul><li>JdbcTemplate</li><li>HibernateTemplate</li></ul></li><li>操作nosql数据库<ul><li>RedisTemplate</li></ul></li><li>操作消息队列<ul><li>JmsTemplate</li></ul></li></ul><h2 id="JdbcTemplate作用"><a href="#JdbcTemplate作用" class="headerlink" title="JdbcTemplate作用"></a>JdbcTemplate作用</h2><p>和数据库交互的模板类</p><h2 id="JdbcTemplate基本用法"><a href="#JdbcTemplate基本用法" class="headerlink" title="JdbcTemplate基本用法"></a>JdbcTemplate基本用法</h2><p>首先通过XML文件配置必要信息，这块是spring框架必要的IOC手法；</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="comment">&lt;!--配置JdbcTemplate--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"jdbcTemplate"</span> <span class="attr">class</span>=<span class="string">"org.springframework.jdbc.core.JdbcTemplate"</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">"dataSource"</span> <span class="attr">ref</span>=<span class="string">"dataSource"</span>&gt;</span><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 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">"dataSource"</span> <span class="attr">class</span>=<span class="string">"org.springframework.jdbc.datasource.DriverManagerDataSource"</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">"driverClassName"</span> <span class="attr">value</span>=<span class="string">"com.mysql.jdbc.Driver"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</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">"url"</span> <span class="attr">value</span>=<span class="string">"jdbc:mysql://localhost:3306/databasename"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</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">"username"</span> <span class="attr">value</span>=<span class="string">"username"</span>&gt;</span><span class="tag">&lt;/<span class="name">property</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">"password"</span> <span class="attr">value</span>=<span class="string">"password"</span>&gt;</span><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><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><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">ApplicationContext ac = <span class="keyword">new</span> ClassPathXmlApplicationContext(<span class="string">"bean.xml"</span>);</span><br><span class="line"><span class="comment">//获取对象</span></span><br><span class="line">JdbcTemplate jt = ac.getBean(<span class="string">"jdbcTemplate"</span>, JdbcTemplate.class);</span><br><span class="line"><span class="comment">//执行操作</span></span><br><span class="line">jt.execute(<span class="string">"insert into account(name, money) values ('name', 222)"</span>);</span><br><span class="line"><span class="comment">//保存</span></span><br><span class="line">jt.update(<span class="string">"insert into account(name, money) values (?, ?)"</span>, <span class="string">"name"</span>, <span class="number">333</span>);</span><br><span class="line"><span class="comment">//更新</span></span><br><span class="line">jt.update(<span class="string">"update account set name=?, money=?, where id=?"</span>,<span class="string">"test"</span>,<span class="number">2345</span>,<span class="number">3</span>);</span><br><span class="line"><span class="comment">//删除</span></span><br><span class="line">jt.update(<span class="string">"delete from account where id=?"</span>, <span class="number">3</span>);</span><br><span class="line"><span class="comment">//查询所有</span></span><br><span class="line">List&lt;Account&gt; accounts = jt.query(<span class="string">"select * from account where money &gt; ?"</span>, <span class="keyword">new</span> AccountRowMapper(), <span class="number">1000f</span>);</span><br><span class="line">List&lt;Account&gt; accounts = jt.query(<span class="string">"select * from account where money &gt; ?"</span>, <span class="keyword">new</span> BeanPropertyRowMapper&lt;Account&gt;(Account.class), <span class="number">1000f</span>);</span><br><span class="line"><span class="keyword">for</span>(Account account : accounts)&#123;</span><br><span class="line">    System.out.println(account);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//查询一个</span></span><br><span class="line">List&lt;Account&gt; accounts = jt.query(<span class="string">"select * from account where id = ?"</span>, <span class="keyword">new</span> BeanPropertyRowMapper&lt;Account&gt;(Account.class), <span class="number">1</span>);</span><br><span class="line"><span class="comment">//查询返回一行一列（使用聚合函数，但是不加group by子句</span></span><br><span class="line">Long count = jt.queryForObject(<span class="string">"select count(*) from account where money &gt; ?"</span>, Long.class, <span class="number">1000f</span>);</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;&lt;strong&gt;是spring框架中提供的一个对象，是对原始Jdbc API对象的简单封装，spring框架提供了许多操作模板类。&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;操作关系型数据&lt;ul&gt;
&lt;li&gt;JdbcTemplate&lt;/li&gt;
&lt;li&gt;HibernateTe
      
    
    </summary>
    
    
      <category term="Spring" scheme="http://zkalan.com/categories/Spring/"/>
    
    
      <category term="spring" scheme="http://zkalan.com/tags/spring/"/>
    
      <category term="JdbcTemplate" scheme="http://zkalan.com/tags/JdbcTemplate/"/>
    
  </entry>
  
  <entry>
    <title>spring基于XML的AOP</title>
    <link href="http://zkalan.com/spring%E5%9F%BA%E4%BA%8EXML%E7%9A%84AOP.html"/>
    <id>http://zkalan.com/spring%E5%9F%BA%E4%BA%8EXML%E7%9A%84AOP.html</id>
    <published>2019-11-11T12:12:00.000Z</published>
    <updated>2025-06-10T19:14:52.026Z</updated>
    
    <content type="html"><![CDATA[<h2 id="配置步骤"><a href="#配置步骤" class="headerlink" title="配置步骤"></a>配置步骤</h2><ol><li>把通知bean也交给spring管理；</li><li>使用aop:config标签表明开始AOP配置；</li><li>使用aop:aspect标签表明配置切面；<ul><li>id属性：给切面提供一个唯一标识</li><li>ref属性：指定通知类bean的id</li></ul></li><li>在aop:aspect标签的内部使用对应标签配置通知的类型；<ul><li>aop:before：表示配置前置通知<ul><li>method：用于指定切面中哪个方法是前置通知；</li><li>pointcut：用于指定切入点表达式，该表达式的含义是指对业务层中哪些方法进行增强</li></ul></li><li>切入点表达式的写法：<ul><li>关键字：execution(表达式)</li><li>表达式：访问修饰符 返回值 类名.方法名(参数列表)<ul><li>访问修饰符可以省略</li><li>返回值可以使用通配符，表示任意返回类型</li><li>包名可以使用通配符，但包的层级需要和通配符一致</li><li>包名可以使用..表示包名及其子包</li><li>类名和方法名可以使用通配符</li><li>全通配写法：* *..*.*(..)</li></ul></li></ul></li></ul></li></ol><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">beans</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">"accountService"</span> <span class="attr">class</span>=<span class="string">"com.service.impl.AccountServiceImpl&gt;&lt;/bean&gt;</span></span></span><br><span class="line"><span class="tag"><span class="string">    &lt;bean id="</span><span class="attr">logger</span>" <span class="attr">class</span>=<span class="string">"com.utils.Logger"</span>&gt;</span><span class="tag">&lt;/<span class="name">bean</span>&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:aspect</span> <span class="attr">id</span>=<span class="string">"logAdvice"</span> <span class="attr">ref</span>=<span class="string">"logger"</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">aop:before</span> <span class="attr">method</span>=<span class="string">"printlog"</span> <span class="attr">pointcut</span>=<span class="string">"execution(public void com.service.AccountServiceImpl.saveAccount())"</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:before</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">aop:aspect</span>&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">beans</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="四种常用通知类型"><a href="#四种常用通知类型" class="headerlink" title="四种常用通知类型"></a>四种常用通知类型</h2><ul><li>aop:before：前置通知，再切入点方法之前执行；</li><li>aop:after-returning：后置通知，在切入点方法正确执行之后执行，它和异常通知永远只有一个执行；</li><li>aop:after-throwing：异常通知，在切入点方法执行产生异常之后执行，它和后置通知永远只能执行一个；</li><li>aop:after：最终通知，无论切入点方法是否正确执行它都会在其后面执行；</li><li>aop:pointcut：配置切入点表达式，id属性用于指定表达式的唯一标识，expression属性用于指定表达式的内容；此标签写在aop:aspect内部时只能当前切面使用，将其写在aop:aspect外面时，所有前面可用；</li><li>aop:around：配置环绕通知；</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;配置步骤&quot;&gt;&lt;a href=&quot;#配置步骤&quot; class=&quot;headerlink&quot; title=&quot;配置步骤&quot;&gt;&lt;/a&gt;配置步骤&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;把通知bean也交给spring管理；&lt;/li&gt;
&lt;li&gt;使用aop:config标签表明开始AOP配置；&lt;/l
      
    
    </summary>
    
    
      <category term="Spring" scheme="http://zkalan.com/categories/Spring/"/>
    
    
      <category term="AOP" scheme="http://zkalan.com/tags/AOP/"/>
    
      <category term="spring" scheme="http://zkalan.com/tags/spring/"/>
    
  </entry>
  
</feed>
