<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>包子哟</title>
  <icon>https://q1.qlogo.cn/g?b=qq&amp;nk=2377743797&amp;s=640</icon>
  
  <link href="https://blog.bugjava.cn/atom.xml" rel="self"/>
  
  <link href="https://blog.bugjava.cn/"/>
  <updated>2024-11-01T12:29:25.604Z</updated>
  <id>https://blog.bugjava.cn/</id>
  
  <author>
    <name>Eternity</name>
    <email>2377743797@qq.com</email>
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>一个简单音乐软件的逆向</title>
    <link href="https://blog.bugjava.cn/post/musicappreverse/"/>
    <id>https://blog.bugjava.cn/post/musicappreverse/</id>
    <published>2024-05-22T08:57:09.000Z</published>
    <updated>2024-11-01T12:29:25.604Z</updated>
    
    <content type="html"><![CDATA[<h1 id="一个音乐app的逆向分析"><a href="#一个音乐app的逆向分析" class="headerlink" title="一个音乐app的逆向分析"></a>一个音乐app的逆向分析</h1><blockquote><p>这个App主要是用来听歌的并且支持下载QQ音乐和网易云的无损音乐，由于想在每个客户端方便的听歌，而且还不需要开会员，就想在网上找类似的网站，偶然间发现了这个App，但是我总不可能在电脑上开模拟器用这个软件吧，于是就有了接下来的事。<psw>偷</psw>（借）接口</p></blockquote><h3 id="第一步：分析一下APK"><a href="#第一步：分析一下APK" class="headerlink" title="第一步：分析一下APK"></a>第一步：分析一下APK</h3><p>对于这类软件，作者一般是会保护一下源代码的，打开MT发现果然加固了</p><p><img src="https://image.bugjava.cn/m/2024/05/25/66517c6eb92ae.png" alt="image-20240525135142134"></p><p>得，先用抓包工具看看有没有有用的数据包</p><h3 id="第二步：抓包"><a href="#第二步：抓包" class="headerlink" title="第二步：抓包"></a>第二步：抓包</h3><p><img src="https://image.bugjava.cn/m/2024/05/25/665180826627a.png" alt="image-20240525140906097"></p><p><img src="https://image.bugjava.cn/m/2024/05/25/665180ed0a780.png"></p><p>很容易就发现了数据就i在这个接口里获取的，那么只需要分析一下请求头信息就好了</p><p>将数据导出到ApiFox里</p><p><img src="https://image.bugjava.cn/m/2024/05/25/665181e7b51fc.png" alt="image-20240525141503577"></p><p>不难发现，这三个参数就是关键信息，都是经过加密的了，那么下一步就要获取加密前的内容和加密方式</p><h3 id="第三步：分析加密接口参数"><a href="#第三步：分析加密接口参数" class="headerlink" title="第三步：分析加密接口参数"></a>第三步：分析加密接口参数</h3><p>启动算法助手，搜索字符串</p><p><img src="https://image.bugjava.cn/m/2024/05/25/665182d1b266b.png" alt="image-20240525141857295"></p><p><img src="https://image.bugjava.cn/m/2024/05/25/665182ff0723b.png" alt="image-20240525141942344"></p><p>请求参数里的sing是用字符串</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span><span class="attr">&quot;act&quot;</span><span class="punctuation">:</span><span class="string">&quot;search&quot;</span><span class="punctuation">,</span><span class="attr">&quot;type&quot;</span><span class="punctuation">:</span><span class="string">&quot;qq&quot;</span><span class="punctuation">,</span><span class="attr">&quot;keywords&quot;</span><span class="punctuation">:</span><span class="string">&quot;%E5%91%A8%E6%9D%B0%E4%BC%A6&quot;</span><span class="punctuation">,</span><span class="attr">&quot;keytype&quot;</span><span class="punctuation">:</span><span class="string">&quot;0&quot;</span><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>加密而来的，lv是确定的，加密密钥是通过其他文本加密的，现在搜索一下这个密钥</p><p><img src="https://image.bugjava.cn/m/2024/05/25/665183c365a65.png" alt="image-20240525142258988"></p><p>很明显是由搜索关键字加上<code>0 + qq + 7c1a11ed25a53751710b51123a4fdc6a</code>组成的字符产的md5值</p><p>因为这个软件有QQ和网易两个接口，所以网易接口的应该就是中间的qq变成了wy</p><p>很轻松的获取到了全部的参数</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></pre></td><td class="code"><pre><span class="line">key = <span class="string">&quot;8FC785DF03E03D12CBA398BDF36CB3F0&quot;</span></span><br><span class="line">data = <span class="string">&#x27;&#123;&quot;act&quot;:&quot;search&quot;,&quot;type&quot;:&quot;qq&quot;,&quot;keywords&quot;:&quot;%E5%91%A8%E6%9D%B0%E4%BC%A6&quot;,&quot;keytype&quot;:&quot;0&quot;&#125;&#x27;</span></span><br><span class="line">lv = <span class="string">&#x27;k1y2a3b4r5t6c7q7&#x27;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>然后用python编写加密代码</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> base64</span><br><span class="line"><span class="keyword">from</span> Crypto.Cipher <span class="keyword">import</span> AES</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">PrpCrypt</span>(<span class="title class_ inherited__">object</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, key</span>):</span><br><span class="line">        <span class="variable language_">self</span>.key = key.encode(<span class="string">&#x27;utf-8&#x27;</span>)</span><br><span class="line">        <span class="variable language_">self</span>.mode = AES.MODE_CBC</span><br><span class="line">        <span class="variable language_">self</span>.iv = <span class="string">&#x27;k1y2a3b4r5t6c7q7&#x27;</span>.encode(<span class="string">&#x27;utf-8&#x27;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">encrypt</span>(<span class="params">self, text</span>):</span><br><span class="line">        text = text.encode(<span class="string">&#x27;utf-8&#x27;</span>)</span><br><span class="line">        cryptor = AES.new(<span class="variable language_">self</span>.key, <span class="variable language_">self</span>.mode, <span class="variable language_">self</span>.iv)</span><br><span class="line">        length = <span class="number">16</span></span><br><span class="line">        count = <span class="built_in">len</span>(text)</span><br><span class="line">        <span class="keyword">if</span> count &lt; length:</span><br><span class="line">            add = (length - count)</span><br><span class="line">            text = text + (<span class="string">&#x27;\0&#x27;</span> * add).encode(<span class="string">&#x27;utf-8&#x27;</span>)</span><br><span class="line">        <span class="keyword">elif</span> count &gt; length:</span><br><span class="line">            add = (length - (count % length))</span><br><span class="line">            text = text + (<span class="string">&#x27;\0&#x27;</span> * add).encode(<span class="string">&#x27;utf-8&#x27;</span>)</span><br><span class="line">        <span class="variable language_">self</span>.ciphertext = cryptor.encrypt(text)</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">self</span>.ciphertext.<span class="built_in">hex</span>()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">decrypt</span>(<span class="params">self, text</span>):</span><br><span class="line">        cryptor = AES.new(<span class="variable language_">self</span>.key, <span class="variable language_">self</span>.mode, <span class="variable language_">self</span>.iv)</span><br><span class="line">        plain_text = cryptor.decrypt(base64.b64decode(text))</span><br><span class="line">        <span class="keyword">return</span> plain_text</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    pc = PrpCrypt(<span class="string">&#x27;5BFDBE2A394F3ADFBDEC604BC39E5206&#x27;</span>)</span><br><span class="line">    e = pc.encrypt(<span class="string">&#x27;&#123;&quot;act&quot;:&quot;search&quot;,&quot;type&quot;:&quot;qq&quot;,&quot;keywords&quot;:&quot;%E5%91%A8%E6%9D%B0%E4%BC%A6&quot;,&quot;keytype&quot;:&quot;0&quot;&#125;&#x27;</span>)</span><br><span class="line">    <span class="built_in">print</span>(e)</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><img src="https://image.bugjava.cn/m/2024/05/25/6651871abf70b.png" alt="image-20240525143714156"></p><p>成功获取到加密后的数据，其他的数据也是类似的方式获取</p><h3 id="第四步：编写测试接口获取数据"><a href="#第四步：编写测试接口获取数据" class="headerlink" title="第四步：编写测试接口获取数据"></a>第四步：编写测试接口获取数据</h3><p><img src="https://image.bugjava.cn/m/2024/05/25/66518815a66bd.png" alt="image-20240525144123553"></p><p>成功获取到搜索的歌曲信息，那么接下来就简单了</p><p><img src="https://image.bugjava.cn/m/2024/05/25/665189dab3933.png" alt="image-20240525144858221"></p><p>歌曲的播放链接获取也是同理，传入的加密前的参数有些许变化</p><figure class="highlight json"><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">搜索的JSON：<span class="punctuation">&#123;</span><span class="attr">&quot;act&quot;</span><span class="punctuation">:</span><span class="string">&quot;search&quot;</span><span class="punctuation">,</span><span class="attr">&quot;type&quot;</span><span class="punctuation">:</span><span class="string">&quot;qq&quot;</span><span class="punctuation">,</span><span class="attr">&quot;keywords&quot;</span><span class="punctuation">:</span><span class="string">&quot;%E5%91%A8%E6%9D%B0%E4%BC%A6&quot;</span><span class="punctuation">,</span><span class="attr">&quot;keytype&quot;</span><span class="punctuation">:</span><span class="string">&quot;0&quot;</span><span class="punctuation">&#125;</span></span><br><span class="line">获取播放链接的JSON：<span class="punctuation">&#123;</span><span class="attr">&quot;act&quot;</span><span class="punctuation">:</span><span class="string">&quot;musicurl&quot;</span><span class="punctuation">,</span><span class="attr">&quot;type&quot;</span><span class="punctuation">:</span><span class="string">&quot;qq&quot;</span><span class="punctuation">,</span><span class="attr">&quot;songid&quot;</span><span class="punctuation">:</span><span class="string">&quot;0039MnYb0qxYhV&quot;</span><span class="punctuation">,</span><span class="attr">&quot;strmid&quot;</span><span class="punctuation">:</span><span class="string">&quot;002202B43Cq4V4&quot;</span><span class="punctuation">,</span><span class="attr">&quot;file&quot;</span><span class="punctuation">:</span><span class="string">&quot;128&quot;</span><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>其中file的值是决定获取到的音质，标准：file &#x3D; 128 高品：file &#x3D; 320 无损：file &#x3D; sq</p><p><img src="https://image.bugjava.cn/m/2024/05/25/6651ad5fd03d2.png" alt="image-20240525172030902"></p><p>编写代码批量下载，完事！</p><blockquote><p>考虑到接口滥用，需要代码学习 评论我发你邮箱</p></blockquote>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;一个音乐app的逆向分析&quot;&gt;&lt;a href=&quot;#一个音乐app的逆向分析&quot; class=&quot;headerlink&quot; title=&quot;一个音乐app的逆向分析&quot;&gt;&lt;/a&gt;一个音乐app的逆向分析&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;这个App主要是用来听歌的并且支持</summary>
      
    
    
    
    <category term="经验教程" scheme="https://blog.bugjava.cn/categories/%E7%BB%8F%E9%AA%8C%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="音乐" scheme="https://blog.bugjava.cn/tags/%E9%9F%B3%E4%B9%90/"/>
    
    <category term="逆向" scheme="https://blog.bugjava.cn/tags/%E9%80%86%E5%90%91/"/>
    
    <category term="无损" scheme="https://blog.bugjava.cn/tags/%E6%97%A0%E6%8D%9F/"/>
    
  </entry>
  
  <entry>
    <title>记录一次简单的电表管理系统（蜂电）破解</title>
    <link href="https://blog.bugjava.cn/post/powerbee_pj/"/>
    <id>https://blog.bugjava.cn/post/powerbee_pj/</id>
    <published>2022-11-10T11:42:06.000Z</published>
    <updated>2025-11-02T06:43:49.662Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>因为前不久刚租房子，今天心血来潮，想看看这么久了花了多少度电，然后打开今天的主角 <psw>Power Bee 蜂电智能电表管理系统</psw></p></blockquote><p>本来想看看每天用了多少电，点击更多居然要我开通VIP，这我能忍？寻思着之前都没有的，应该是最近才加上的。</p><p><img src="https://s2.loli.net/2022/11/10/xmVtZupLgMwGOh1.png"></p><p>然后果断的打开了抓包工具，看看你到底是个啥。有没有什么破解方法</p><p>果然，简简单单的获取到了一条请求，这个请求里面刚好是两条数据</p><p><img src="https://s2.loli.net/2022/11/10/1mwUJDp24BfOCj9.png" alt="获取到的数据"></p><p><img src="https://s2.loli.net/2022/11/10/jdDhFKucaXfkoT4.png" alt="JSON字段"></p><p>然后看一下请求头</p><figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">GET</span> <span class="string">http://im.zg118.com/api/client/ammeter/report/**********/2022-11-09/2022-11-11?uid=**********&amp;token=**********</span> <span class="meta">HTTP/1.1</span></span><br><span class="line"><span class="attribute">Host</span><span class="punctuation">: </span>im.zg118.com</span><br><span class="line"><span class="attribute">Connection</span><span class="punctuation">: </span>keep-alive</span><br><span class="line"><span class="attribute">Accept</span><span class="punctuation">: </span>application/json, text/javascript, */*; q=0.01</span><br><span class="line"><span class="attribute">User-Agent</span><span class="punctuation">: </span>Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 NetType/WIFI MicroMessenger/7.0.20.1781(0x6700143B) WindowsWechat(0x6307062c)</span><br><span class="line"><span class="attribute">X-Requested-With</span><span class="punctuation">: </span>XMLHttpRequest</span><br><span class="line"><span class="attribute">Cookie</span><span class="punctuation">: </span>***********</span><br><span class="line"><span class="attribute">Referer</span><span class="punctuation">: </span>http://im.zg118.com/static/weixin/report.html*</span><br><span class="line"><span class="attribute">Accept-Encoding</span><span class="punctuation">: </span>gzip, deflate</span><br><span class="line"><span class="attribute">Accept-Language</span><span class="punctuation">: </span>zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7</span><br></pre></td></tr></table></figure><p>很明显，主要就是通过get请求的<code>uid</code>和<code>token</code>确定身份，请求中的时间来选定查询的日期</p><p>接下来，修改时间请求一次</p><p><img src="https://s2.loli.net/2022/11/10/CWTnq37GBlapJgO.png" alt="修改后的请求"></p><p>果然，就和我猜的一样，才上线的VIP系统，大概率没有鉴权，</p><p>这样就可以获取到全部日期的电费记录了，</p><p>为了方便查看电脑，搞了个简单的查询网页</p><hr><iframe style="width: 100%;height: 600px;border: #49b1f5 solid 1px;" allow="clipboard-read; clipboard-write" src="/html/powerbee.html"></iframe>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;因为前不久刚租房子，今天心血来潮，想看看这么久了花了多少度电，然后打开今天的主角 &lt;psw&gt;Power Bee 蜂电智能电表管理系统&lt;/psw&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;本来想看看每天用了多少电，点击更多居然要我开通VIP，这我能</summary>
      
    
    
    
    <category term="经验教程" scheme="https://blog.bugjava.cn/categories/%E7%BB%8F%E9%AA%8C%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="powerbee" scheme="https://blog.bugjava.cn/tags/powerbee/"/>
    
  </entry>
  
  <entry>
    <title>vue2和vue3响应式实现区别</title>
    <link href="https://blog.bugjava.cn/post/vue1/"/>
    <id>https://blog.bugjava.cn/post/vue1/</id>
    <published>2022-10-23T13:42:06.000Z</published>
    <updated>2023-04-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h3 id="vue2-x的响应式"><a href="#vue2-x的响应式" class="headerlink" title="vue2.x的响应式"></a>vue2.x的响应式</h3><ul><li><p>实现原理：</p><ul><li><p>对象类型：通过<code>Object.defineProperty()</code>对属性的读取、修改进行拦截（数据劫持）。</p></li><li><p>数组类型：通过重写更新数组的一系列方法来实现拦截。（对数组的变更方法进行了包裹）。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(data, <span class="string">&#x27;count&#x27;</span>, &#123;</span><br><span class="line">    <span class="title function_">get</span> () &#123;&#125;, </span><br><span class="line">    <span class="title function_">set</span> () &#123;&#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure></li></ul></li><li><p>存在问题：</p><ul><li>新增属性、删除属性, 界面不会更新。</li><li>直接通过下标修改数组, 界面不会自动更新。</li></ul></li></ul><h3 id="Vue3-0的响应式"><a href="#Vue3-0的响应式" class="headerlink" title="Vue3.0的响应式"></a>Vue3.0的响应式</h3><ul><li>实现原理: <ul><li>通过Proxy（代理）:  拦截对象中任意属性的变化, 包括：属性值的读写、属性的添加、属性的删除等。</li><li>通过Reflect（反射）:  对源对象的属性进行操作。</li><li>MDN文档中描述的Proxy与Reflect：<ul><li><p>Proxy：<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy</a></p></li><li><p>Reflect：<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect">https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect</a></p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> <span class="title class_">Proxy</span>(data, &#123;</span><br><span class="line"><span class="comment">// 拦截读取属性值</span></span><br><span class="line">    <span class="title function_">get</span> (target, prop) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Reflect</span>.<span class="title function_">get</span>(target, prop)</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 拦截设置属性值或添加新属性</span></span><br><span class="line">    <span class="title function_">set</span> (target, prop, value) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Reflect</span>.<span class="title function_">set</span>(target, prop, value)</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 拦截删除属性</span></span><br><span class="line">    <span class="title function_">deleteProperty</span> (target, prop) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Reflect</span>.<span class="title function_">deleteProperty</span>(target, prop)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">proxy.<span class="property">name</span> = <span class="string">&#x27;tom&#x27;</span>   </span><br></pre></td></tr></table></figure></li></ul></li></ul></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;vue2-x的响应式&quot;&gt;&lt;a href=&quot;#vue2-x的响应式&quot; class=&quot;headerlink&quot; title=&quot;vue2.x的响应式&quot;&gt;&lt;/a&gt;vue2.x的响应式&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;实现原理：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;对象类型：通过</summary>
      
    
    
    
    <category term="Vue" scheme="https://blog.bugjava.cn/categories/Vue/"/>
    
    
    <category term="Vue" scheme="https://blog.bugjava.cn/tags/Vue/"/>
    
    <category term="JavaScript" scheme="https://blog.bugjava.cn/tags/JavaScript/"/>
    
  </entry>
  
  <entry>
    <title>Spring笔记</title>
    <link href="https://blog.bugjava.cn/post/Spring-stduy/"/>
    <id>https://blog.bugjava.cn/post/Spring-stduy/</id>
    <published>2022-05-01T07:34:06.000Z</published>
    <updated>2023-04-08T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h4 id="1-什么是Spring框架"><a href="#1-什么是Spring框架" class="headerlink" title="1.什么是Spring框架"></a>1.什么是Spring框架</h4><p>  它是一个容器.它是整合其它框架的框架.它的核心是IOC和AOP.它由20多个模块构成.它在很多领域都提供优秀的解决方案.</p><h4 id="2-Spring的特点"><a href="#2-Spring的特点" class="headerlink" title="2.Spring的特点"></a>2.Spring的特点</h4><p>  1)轻量级<br>  由20多个模块构成,每个jar包都很小,小于1M,核心包也就3M左右.<br>  对代码无污染.</p><p>  2)面向接口编程<br>  使用接口,就是面向灵活,项目的可扩展性,可维护性都极高.接口不关心实现类的类型.使用时接口指向实现类,切换实现类即可切换整个功能.</p><p>  3)AOP:面向切面编程<br>  就是将公共的,通用的,重复的代码单独开发,在需要的时候反织回去.底层的原理是动态代理.</p><p>  4)整合其它框架<br>  它整合后使其它框架更易用.</p><h4 id="3-什么是IOC"><a href="#3-什么是IOC" class="headerlink" title="3.什么是IOC"></a>3.什么是IOC</h4><p>  控制反转IoC(Inversion of Control)是一个概念，是一种思想。由Spring容器进行对象的创建和依赖注入.程序员在使用时直接取出使用.</p><p>  正转:由程序员进行对象的创建和依赖注入称为正转.程序员说了算.<br>  Student stu &#x3D; new Student();   &#x3D;&#x3D;&#x3D;&gt;程序员创建对象<br>  stu.setName(“张三”);           &#x3D;&#x3D;&#x3D;&gt;程序员进行赋值<br>  stu.setAge(22);</p><p>  反转:由Spring容器创建对象和依赖注入称为反转,将控制权从程序员手中夺走,由给Spring容器,称为反转. 容器说了算.<br>  <bean id="stu" class="com.bjpowernode.pojo.Student">     &#x3D;&#x3D;&#x3D;&gt;Spring容器负责对象的创建<br>    <property name="name" value="张三">                    &#x3D;&#x3D;&#x3D;&gt;Spring容器依赖注入值<br>    <property name="age" value="22"><br>  </bean></p><p>  切记:Spring容器在启动时,就创建所有的对象stu….</p><h4 id="4-基于xml的IOC"><a href="#4-基于xml的IOC" class="headerlink" title="4.基于xml的IOC"></a>4.基于xml的IOC</h4><p>  1)创建对象<br>  <bean id="stu" class="com.bjpowernode.pojo.Student"></bean></p><p>  2)给创建的对象赋值<br>    A.使用setter注入<br>      注入分为简单类型注入和引用类型注入<br>      简单类型注入值使用value属性<br>      引用类型注入值使用ref属性<br>      必须要注意:使用setter注入必须提供无参的构造方法,必须提供setXXX()方法.</p><p>​    </p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--创建学生对象--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;stu&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.pojo2.Student&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;李四&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span>    ===&gt;简单类型注入</span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span> <span class="attr">value</span>=<span class="string">&quot;22&quot;</span>&gt;</span><span 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">&quot;school&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;school&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span>  ===&gt;引用类型注入</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">&quot;school&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.pojo2.School&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;清华大学&quot;</span>&gt;</span><span 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">&quot;address&quot;</span> <span class="attr">value</span>=<span class="string">&quot;海淀区&quot;</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><p>​<br>​    </p><p>B.使用构造方法注入<br>Student stu &#x3D; new Student(“张三”,22);<br>   a.使用构造方法的参数名称进行注入值</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;school&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.pojo3.School&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">name</span>=<span class="string">&quot;name1&quot;</span> <span class="attr">value</span>=<span class="string">&quot;清华大学&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">constructor-arg</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">name</span>=<span class="string">&quot;address1&quot;</span> <span class="attr">value</span>=<span class="string">&quot;海淀区&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">constructor-arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure><p>   b.使用构造方法参数的下标注入值</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">bean</span> <span class="attr">id</span>=<span class="string">&quot;stu&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.pojo3.Student&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">index</span>=<span class="string">&quot;0&quot;</span> <span class="attr">value</span>=<span class="string">&quot;钱七&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">constructor-arg</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">index</span>=<span class="string">&quot;1&quot;</span> <span class="attr">value</span>=<span class="string">&quot;22&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">constructor-arg</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">index</span>=<span class="string">&quot;2&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;school&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">constructor-arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure><p>   c.使用默认的构造方法的参数的顺序注入值   </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">bean</span> <span class="attr">id</span>=<span class="string">&quot;stuSequence&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.pojo3.Student&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">value</span>=<span class="string">&quot;陈十&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">constructor-arg</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">value</span>=<span class="string">&quot;22&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">constructor-arg</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">ref</span>=<span class="string">&quot;school&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">constructor-arg</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure><h4 id="5-项目案例"><a href="#5-项目案例" class="headerlink" title="5.项目案例"></a>5.项目案例</h4><p>  使用三层架构进行用户的插入操作.<br>  界面层,业务逻辑层,数据访问层(模拟).</p><p>  Spring会接管三层架构中哪些对象的创建?界面层的对象,业务逻辑层的对象,数据访问层的对象.</p><p>  非Spring接管下的三层项目构建:<br>  实体类<br>  com.bjpowernode.pojo  Users<br>  数据访问层<br>  com.bjpowernode.dao   UsersMapper.java(接口)<br>  UsersMapperImpl.java(实现类)<br>  业务逻辑层<br>  com.bjpowernode.service   UsersService.java(接口)<br>  UsersServiceImpl.java(实现类 )<br>  界面层<br>  com.bjpowernode.controller  UsersController.java</p><h4 id="6-基于注解的IOC"><a href="#6-基于注解的IOC" class="headerlink" title="6.基于注解的IOC"></a>6.基于注解的IOC</h4><p>  也称为DI(Dependency Injection),它是IOC的具体实现的技术.</p><p>  基于注解的IOC,必须要在Spring的核心配置文件中添加包扫描.<br>  &lt;context:component-scan base-package&#x3D;”com.bjpowernode.s01”&gt;</context:component-scan></p><p>  药:  创建对象并依赖注入<br>  汤:   xml    注解annotation<br>  1)创建对象的注解<br>@Component:可以创建任意对象.创建的对象的默认名称是类名的驼峰命名法.也可以指定对象的名称@Component(“指定名称”).<br>@Controller:专门用来创建控制器的对象(Servlet),这种对象可以接收用户的请求,可以返回处理结果给客户端.<br>@Service:专门用来创建业务逻辑层的对象,负责向下访问数据访问层,处理完毕后的结果返回给界面层.<br>@Repository:专门用来创建数据访问层的对象,负责数据库中的增删改查所有操作.<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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component(&quot;stu&quot;)</span>  <span class="comment">//交给Spring去创建对象,就是在容器启动时创建</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Student</span> &#123;</span><br><span class="line">    <span class="meta">@Value(&quot;张三&quot;)</span>  ===&gt;简单类型的值注入</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="meta">@Value(&quot;22&quot;)</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> age;</span><br><span class="line">    ...&#125;</span><br></pre></td></tr></table></figure><p>  2)依赖注入的注解<br>    简单类型(8种基本类型+String)的注入<br>@Value:用来给简单类型注入值</p><p>引用类型的注入<br>A.@Autowired:使用类型注入值,从整个Bean工厂中搜索同源类型的对象进行注入.<br>同源类型也可注入.<br>什么是同源类型:<br>  a.被注入的类型(Student中的school)与注入的类型是完全相同的类型<br>  b.被注入的类型(Student中的school父)与注入的类型(子)是父子类<br>  c.被注入的类型(Student中的school接口)与注入的类型(实现类)是接口和实现类的类型</p><p>注意:在有父子类的情况下,使用按类型注入,就意味着有多个可注入的对象.此时按照名称进行二次筛选,选中与被注入对象相同名称的对象进行注入.</p><p>B.@Autowired<br>  @Qualifier(“名称”):使用名称注入值,从整个Bean工厂中搜索相同名称的对象进行注入.</p><p>注意:如果有父子类的情况下,直接按名称进行注入值.</p><h4 id="7-添加包扫描的方式"><a href="#7-添加包扫描的方式" class="headerlink" title="7.添加包扫描的方式"></a>7.添加包扫描的方式</h4><p>  1)单个包扫描(推荐使用)</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></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.bjpowernode.controller&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.bjpowernode.service.impl&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.bjpowernode.dao&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br></pre></td></tr></table></figure><p>  2)多个包扫描,多个包之间以逗号或空格或分号分隔</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.bjpowernode.controller com.bjpowernode.service ,com.bjpowernode.dao&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br></pre></td></tr></table></figure><p>  3)扫描根包(不推荐)</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.bjpowernode&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br></pre></td></tr></table></figure><p>​    会降低容器启动的速度,导致多做无用功.</p><h4 id="8-为应用指定多个-Spring-配置文件"><a href="#8-为应用指定多个-Spring-配置文件" class="headerlink" title="8.为应用指定多个 Spring 配置文件"></a>8.为应用指定多个 Spring 配置文件</h4><p>  当项目越来越大,需要多人合作开发,一个配置就存在很大隐患.<br>  1)拆分配置文件的策略<br>    A.按层拆</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></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--applicationContext_controller.xml--&gt;</span>      </span><br><span class="line">        <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;uController&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.controller.UsersController&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;bController&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.controller.BookController&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><p>​     </p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--applicationContext_service.xml--&gt;</span>     </span><br><span class="line">        <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;uService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.controller.UsersService&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;bService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.controller.BookService&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--applicationContext_mapper.xml--&gt;</span>  </span><br><span class="line">        <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;uMapper&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.controller.UsersMapper&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;bMapper&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.controller.BookMapper&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><p>B.按功能拆<br>  applicationContext_users.xml        </p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;uController&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.controller.UsersController&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;uService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.controller.UsersService&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;uMapper&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.controller.UsersMapper&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><p>  applicationContext_book.xml      </p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;bController&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.controller.BookController&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;bService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.controller.BookService&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;bMapper&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.bjpowernode.controller.BookMapper&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><h4 id="9-spring配置文件的整合"><a href="#9-spring配置文件的整合" class="headerlink" title="9.spring配置文件的整合"></a>9.spring配置文件的整合</h4><p>  1)单个文件导入 </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></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">import</span> <span class="attr">resource</span>=<span class="string">&quot;applicatoinContext_mapper.xml&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">import</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">import</span> <span class="attr">resource</span>=<span class="string">&quot;applicatoinContext_service.xml&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">import</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;<span class="name">import</span> <span class="attr">resource</span>=<span class="string">&quot;applicatoinContext_controller.xml&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">import</span>&gt;</span></span><br></pre></td></tr></table></figure><p>  2)批量导入</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">import</span> <span class="attr">resource</span>=<span class="string">&quot;applicatoinContext_*.xml&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">import</span>&gt;</span></span><br></pre></td></tr></table></figure><h4 id="10-面向切面编程AOP"><a href="#10-面向切面编程AOP" class="headerlink" title="10.面向切面编程AOP"></a>10.面向切面编程AOP</h4><p>  AOP（Aspect Orient Programming），面向切面编程。<br>  切面:公共的,通用的,重复的功能称为切面,面向切面编程就是将切面提取出来,单独开发,在需要调用的方法中通过动态代理的方式进行织入.</p><h4 id="11-手写AOP框架"><a href="#11-手写AOP框架" class="headerlink" title="11.手写AOP框架"></a>11.手写AOP框架</h4><p>  业务:图书购买业务<br>  切面:事务<br>  1)第一个版本:业务和切面紧耦合在一起,没有拆分.<br>  2)第二个版本:使用子类代理的方式拆分业务和切面.<br>  3)第三个版本:使用静态代理拆分业务和切面.业务和业务接口已拆分.此时切面紧耦合在业务中.<br>  4)第四个版本:使用静态代理拆分业务和业务接口,切面和切面接口.<br>  5)第五个版本:使用动态代理完成第四个版本的优化.</p><h4 id="12-Spring支持的AOP的实现"><a href="#12-Spring支持的AOP的实现" class="headerlink" title="12.Spring支持的AOP的实现"></a>12.Spring支持的AOP的实现</h4><p>  Spring支持AOP的编程，常用的有以下几种：<br>  1)Before通知：在目标方法被调用前调用，涉及接口org.springframework.aop.MethodBeforeAdvice;<br>  2)After通知：在目标方法被调用后调用，涉及接口为org.springframework.aop.AfterReturningAdvice;<br>  3)Throws通知：目标方法抛出异常时调用，涉及接口org.springframework.aop.ThrowsAdvice;<br>  4)Around通知：拦截对目标对象方法调用，涉及接口为org.aopalliance.intercept.MethodInterceptor。</p><h4 id="13-AOP常用的术语"><a href="#13-AOP常用的术语" class="headerlink" title="13.AOP常用的术语"></a>13.AOP常用的术语</h4><p>  1)切面:就是那些重复的,公共的,通用的功能称为切面,例如:日志,事务,权限.<br>  2)连接点:就是目标方法.因为在目标方法中要实现目标方法的功能和切面功能.<br>  3)切入点(Pointcut):指定切入的位置,多个连接点构成切入点.切入点可以是一个目标方法,可以是一个类中的所有方法,可以是某个包下的所有类中的方法.<br>  4)目标对象:操作谁,谁就是目标对象.<br>  5)通知(Advice):来指定切入的时机.是在目标方法执行前还是执行后还是出错时,还是环绕目标方法切入切面功能.</p><h4 id="14-什么是AspectJ框架"><a href="#14-什么是AspectJ框架" class="headerlink" title="14.什么是AspectJ框架"></a>14.什么是AspectJ框架</h4><p>  AspectJ 是一个优秀面向切面的框架，它扩展了 Java 语言，提供了强大的切面实现。它因为是基于java语言开发的,所以无缝扩展.easy to learn and use（易学易用）.</p><h4 id="15-AspectJ常见通知类型"><a href="#15-AspectJ常见通知类型" class="headerlink" title="15.AspectJ常见通知类型"></a>15.AspectJ常见通知类型</h4><p>  AspectJ 中常用的通知有四种类型：<br>  1)前置通知@Before<br>  2)后置通知@AfterReturning<br>  3)环绕通知@Around<br>  4)最终通知@After<br>  5)定义切入点@Pointcut(了解)</p><h4 id="16-AspectJ-的切入点表达式-掌握"><a href="#16-AspectJ-的切入点表达式-掌握" class="headerlink" title="16.AspectJ 的切入点表达式(掌握)"></a>16.AspectJ 的切入点表达式(掌握)</h4><p>  规范的公式:<br>  execution(访问权限 方法返回值 方法声明(参数) 异常类型)<br>  简化后的公式:<br>  execution( 方法返回值 方法声明(参数) )</p><p>  用到的符号:</p><ul><li>代码任意个任意的字符(通配符)<br>..  如果出现在方法的参数中,则代表任意参数<br>如果出现在路径中,则代表本路径及其所有的子路径</li></ul><p>  示例:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">execution(public * *(..)) :任意的公共方法</span><br><span class="line"> execution(* set*(..)):任何一个以“set”开始的方法</span><br><span class="line"> execution(* com.xyz.service.impl.*.*(..)):任意的返回值类型,在com.xyz.service.impl包下的任意类的任意方法的任意参数</span><br><span class="line"> execution(* com.xyz.service..*.*(..)):任意的返回值类型 ,在com.xyz.service及其子包下的任意类的任意方法的任意参数  </span><br><span class="line">  com.xyz.service.a.b.*.*(..)  com.xyz.service.*.*(..)</span><br><span class="line"> execution(* *..service.*.*(..)):service之前可以有任意的子包</span><br><span class="line"> execution(* *.service.*.*(..)):service之前只有一个包</span><br></pre></td></tr></table></figure><h4 id="17-AspectJ的前置通知-Before"><a href="#17-AspectJ的前置通知-Before" class="headerlink" title="17.AspectJ的前置通知@Before"></a>17.AspectJ的前置通知@Before</h4><p>  在目标方法执行前切入切面功能.在切面方法中不可以获得目标方法的返回值,只能得到目标方法的签名.</p><p>  实现的步骤:<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">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-aspects<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.2.5.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><p>  1)创建业务接口<br>  2)创建业务实现<br>  3)创建切面类,实现切面方法<br>  4)在applicationContext.xml文件中进行切面绑定</p><p>  项目案例:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Aspect</span>  <span class="comment">//交给AspectJ的框架去识别切面类</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyAspect</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 所有切面的功能都是由切面方法来实现的</span></span><br><span class="line"><span class="comment">     * 可以将各种切面都在此类中进行开发</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 前置通知的切面方法的规范</span></span><br><span class="line"><span class="comment">     * 1)访问权限是public</span></span><br><span class="line"><span class="comment">     * 2)方法的返回值是void</span></span><br><span class="line"><span class="comment">     * 3)方法名称自定义</span></span><br><span class="line"><span class="comment">     * 4)方法没有参数,如果有也只能是JoinPoint类型</span></span><br><span class="line"><span class="comment">     * 5)必须使用<span class="doctag">@Before</span>注解来声明切入的时机是前切功能和切入点</span></span><br><span class="line"><span class="comment">     *   参数:value  指定切入点表达式</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 业务方法</span></span><br><span class="line"><span class="comment">     * public String doSome(String name, int age)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Before(value = &quot;execution(public String com.bjpowernode.s01.SomeServiceImpl.*(String,int))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">myBefore</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;切面方法中的前置通知功能实现............&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Before(value = &quot;execution(public * com.bjpowernode.s01.SomeServiceImpl.*(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">myBefore</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;切面方法中的前置通知功能实现............&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Before(value = &quot;execution( * com.bjpowernode.s01.*.*(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">myBefore</span><span class="params">(JoinPoint jp)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;切面方法中的前置通知功能实现............&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;目标方法的签名:&quot;</span>+jp.getSignature());</span><br><span class="line">        System.out.println(<span class="string">&quot;目标方法的参数:&quot;</span>+ Arrays.toString(jp.getArgs()));</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Before(value = &quot;execution( * com.bjpowernode.s01..*(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">myBefore</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;切面方法中的前置通知功能实现............&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Before(value = &quot;execution( * *(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">myBefore</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;切面方法中的前置通知功能实现............&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="18-AspectJ框架切换JDK动态代理和CGLib动态代理"><a href="#18-AspectJ框架切换JDK动态代理和CGLib动态代理" class="headerlink" title="18.AspectJ框架切换JDK动态代理和CGLib动态代理"></a>18.AspectJ框架切换JDK动态代理和CGLib动态代理</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">aop:aspectj-autoproxy</span> &gt;</span><span class="tag">&lt;/<span class="name">aop:aspectj-autoproxy</span>&gt;</span>  ===&gt;默认是JDK动态代理,取时必须使用接口类型</span><br><span class="line"><span class="tag">&lt;<span class="name">aop:aspectj-autoproxy</span> <span class="attr">proxy-target-class</span>=<span class="string">&quot;true&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:aspectj-autoproxy</span>&gt;</span>  ==&gt;设置为CGLib子类代理,可以使用接口和实现类接</span><br></pre></td></tr></table></figure><p>​    记住:使用接口来接,永远不出错.</p><h4 id="19-AfterReturning后置通知"><a href="#19-AfterReturning后置通知" class="headerlink" title="19.@AfterReturning后置通知"></a>19.@AfterReturning后置通知</h4><p>   后置通知是在目标方法执行后切入切面功能,可以得到目标方法的返回值.如果目标方法的返回值是简单类型(8种基本类型+String)则不可改变.如果目标方法的返回值是引用类型则可以改变.</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyAspect</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 后置通知的方法的规范</span></span><br><span class="line"><span class="comment">     * 1)访问权限是public</span></span><br><span class="line"><span class="comment">     * 2)方法没有返回值void</span></span><br><span class="line"><span class="comment">     * 3)方法名称自定义</span></span><br><span class="line"><span class="comment">     * 4)方法有参数(也可以没有参数,如果目标方法没有返回值,则可以写无参的方法,但一般会写有参,这样可以处理无参可以处理有参),这个切面方法的参数就是目标方法的返回值</span></span><br><span class="line"><span class="comment">     * 5)使用<span class="doctag">@AfterReturning</span>注解表明是后置通知</span></span><br><span class="line"><span class="comment">     *   参数:</span></span><br><span class="line"><span class="comment">     *      value:指定切入点表达式</span></span><br><span class="line"><span class="comment">     *      returning:指定目标方法的返回值的名称,则名称必须与切面方法的参数名称一致.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@AfterReturning(value = &quot;execution(* com.bjpowernode.s02.*.*(..))&quot;,returning = &quot;obj&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">myAfterReturning</span><span class="params">(Object obj)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;后置通知功能实现..............&quot;</span>);</span><br><span class="line">        <span class="keyword">if</span>(obj != <span class="literal">null</span>)&#123;</span><br><span class="line">            <span class="keyword">if</span>(obj <span class="keyword">instanceof</span> String)&#123;</span><br><span class="line">                obj = obj.toString().toUpperCase();</span><br><span class="line">                System.out.println(<span class="string">&quot;在切面方法中目标方法的返回值:&quot;</span>+obj);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span>(obj <span class="keyword">instanceof</span> Student)&#123;</span><br><span class="line">                <span class="type">Student</span> <span class="variable">stu</span> <span class="operator">=</span> (Student) obj;</span><br><span class="line">                stu.setName(<span class="string">&quot;李四&quot;</span>);</span><br><span class="line">                System.out.println(<span class="string">&quot;在切面方法中目标方法的返回值:&quot;</span>+stu);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="20-环绕通知-Around"><a href="#20-环绕通知-Around" class="headerlink" title="20.环绕通知@Around"></a>20.环绕通知@Around</h4><p>  它是通过拦截目标方法的方式 ,在目标方法前后增强功能的通知.它是功能最强大的通知,一般事务使用此通知.它可以轻易的改变目标方法的返回值.</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyAspect</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 环绕通知方法的规范</span></span><br><span class="line"><span class="comment">     * 1)访问权限是public</span></span><br><span class="line"><span class="comment">     * 2)切面方法有返回值,此返回值就是目标方法的返回值</span></span><br><span class="line"><span class="comment">     * 3)方法名称自定义</span></span><br><span class="line"><span class="comment">     * 4)方法有参数,此参数就是目标方法</span></span><br><span class="line"><span class="comment">     * 5)回避异常Throwable</span></span><br><span class="line"><span class="comment">     * 6)使用<span class="doctag">@Around</span>注解声明是环绕通知</span></span><br><span class="line"><span class="comment">     *   参数:</span></span><br><span class="line"><span class="comment">     *      value:指定切入点表达式</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Around(value = &quot;execution(* com.bjpowernode.s03.*.*(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">myAround</span><span class="params">(ProceedingJoinPoint pjp)</span> <span class="keyword">throws</span> Throwable &#123;</span><br><span class="line">        <span class="comment">//前切功能实现</span></span><br><span class="line">        System.out.println(<span class="string">&quot;环绕通知中的前置功能实现............&quot;</span>);</span><br><span class="line">        <span class="comment">//目标方法调用</span></span><br><span class="line">        <span class="type">Object</span> <span class="variable">obj</span> <span class="operator">=</span> pjp.proceed(pjp.getArgs());</span><br><span class="line">        <span class="comment">//后切功能实现</span></span><br><span class="line">        System.out.println(<span class="string">&quot;环绕通知中的后置功能实现............&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> obj.toString().toUpperCase();  <span class="comment">//改变了目标方法的返回值</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="21-最终通知-After"><a href="#21-最终通知-After" class="headerlink" title="21.最终通知@After"></a>21.最终通知@After</h4><p>  无论目标方法是否正常执行,最终通知的代码都会被执行.</p><h4 id="22-给切入点表达式起别名-Pointcut"><a href="#22-给切入点表达式起别名-Pointcut" class="headerlink" title="22.给切入点表达式起别名@Pointcut"></a>22.给切入点表达式起别名@Pointcut</h4><p>  如果多个切面切入到同一个切入点,可以使用别名简化开发.<br>  使用@Pointcut注解,创建一个空方法,此方法的名称就是别名.<br>  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">   <span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyAspect</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 最终通知方法的规范</span></span><br><span class="line"><span class="comment">     * 1)访问权限是public</span></span><br><span class="line"><span class="comment">     * 2)方法没有返回值</span></span><br><span class="line"><span class="comment">     * 3)方法名称自定义</span></span><br><span class="line"><span class="comment">     * 4)方法没有参数,如果有也只能是JoinPoint</span></span><br><span class="line"><span class="comment">     * 5)使用<span class="doctag">@After</span>注解表明是最终通知</span></span><br><span class="line"><span class="comment">     *   参数:</span></span><br><span class="line"><span class="comment">     *     value:指定切入点表达式</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@After(value = &quot;mycut()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">myAfter</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;最终通知的功能........&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Before(value = &quot;mycut()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">myBefore</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;前置通知的功能........&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterReturning(value = &quot;mycut()&quot;,returning = &quot;obj&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">myAfterReturning</span><span class="params">(Object obj)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;后置通知的功能........&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Around(value = &quot;mycut()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">myAround</span><span class="params">(ProceedingJoinPoint pjp)</span> <span class="keyword">throws</span> Throwable &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;环绕通知中的前置通知的功能........&quot;</span>);</span><br><span class="line">        <span class="type">Object</span> <span class="variable">obj</span> <span class="operator">=</span> pjp.proceed(pjp.getArgs());</span><br><span class="line">        System.out.println(<span class="string">&quot;环绕通知中的后置通知的功能........&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> obj;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Pointcut(value = &quot;execution(* com.bjpowernode.s04.*.*(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">mycut</span><span class="params">()</span>&#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><h4 id="23-SM整合的步骤"><a href="#23-SM整合的步骤" class="headerlink" title="23.SM整合的步骤"></a>23.SM整合的步骤</h4><p>  1)建表<br>  2)新建项目,选择quickstart模板<br>  3)修改目录<br>  4)修改pom.xml文件,添加相关的依赖(使用老师提供)<br>  5)添加MyBatis相应的模板(SqlMapConfig.xml和XXXMapper.xml文件)<br>  6)添加SqlMapConfig.xml文件(MyBatis核心配置文件),并拷贝jdbc.propertiest属性文件到resources目录下<br>  7)添加applicationContext_mapper.xml<br>  8)添加applicationContext_service.xml<br>  9)添加Users实体类,Accounts实体类<br>  10)添加mapper包,添加UsersMapper接口和UsersMapper.xml文件并开发<br>  11)添加service包,添加UsersService接口和UsersServiceImpl实现类<br>  12)添加测试类进行功能测试</p><h4 id="24-基于注解的事务添加步骤"><a href="#24-基于注解的事务添加步骤" class="headerlink" title="24.基于注解的事务添加步骤"></a>24.基于注解的事务添加步骤</h4><p>  1)在applicationContext_service.xml文件中添加事务管理器</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;transactionManager&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;</span>&gt;</span></span><br><span class="line">     <span class="comment">&lt;!--因为事务必须关联数据库处理,所以要配置数据源--&gt;</span></span><br><span class="line">     <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;dataSource&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure><p>  2)在applicationContext_service.xml文件中添加事务的注解驱动</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">tx:annotation-driven</span> <span class="attr">transaction-manager</span>=<span class="string">&quot;transactionManager&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">tx:annotation-driven</span>&gt;</span></span><br></pre></td></tr></table></figure><p>  3)在业务逻辑的实现类上添加注解@Transactional(propagation &#x3D; Propagation.REQUIRED)<br>    REQUIRED表示增删改操作时必须添加的事务传播特性</p><h4 id="25-Transactional注解参数详解"><a href="#25-Transactional注解参数详解" class="headerlink" title="25.@Transactional注解参数详解"></a>25.@Transactional注解参数详解</h4><p>​</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Transactional(propagation = Propagation.REQUIRED,//事务的传播特性</span></span><br><span class="line"><span class="meta">        noRollbackForClassName = &quot;ArithmeticException&quot;, //指定发生什么异常不回滚,使用的是异常的名称</span></span><br><span class="line"><span class="meta">        noRollbackFor = ArithmeticException.class,//指定发生什么异常不回滚,使用的是异常的类型</span></span><br><span class="line"><span class="meta">        rollbackForClassName = &quot;&quot;,//指定发生什么异常必须回滚</span></span><br><span class="line"><span class="meta">        rollbackFor = ArithmeticException.class,//指定发生什么异常必须回滚</span></span><br><span class="line"><span class="meta">        timeout = -1, //连接超时设置,默认值是-1,表示永不超时</span></span><br><span class="line"><span class="meta">        readOnly = false, //默认是false,如果是查询操作,必须设置为true.</span></span><br><span class="line"><span class="meta">        isolation = Isolation.DEFAULT//使用数据库自已的隔离级别        </span></span><br><span class="line"><span class="meta">              )</span></span><br></pre></td></tr></table></figure><h4 id="26-Spring的两种事务处理方式"><a href="#26-Spring的两种事务处理方式" class="headerlink" title="26.Spring的两种事务处理方式"></a>26.Spring的两种事务处理方式</h4><p>  1)注解式的事务<br>    使用@Transactional注解完成事务控制,此注解可添加到类上,则对类中所有方法执行事务的设定.此注解可添加到方法上,只是对此方法执行事务的处理.</p><p>  2)声明式事务(必须掌握),在配置文件中添加一次,整个项目遵循事务的设定.</p><h4 id="27-Spring中事务的五大隔离级别"><a href="#27-Spring中事务的五大隔离级别" class="headerlink" title="27.Spring中事务的五大隔离级别"></a>27.Spring中事务的五大隔离级别</h4><p>  1).未提交读(Read Uncommitted)：允许脏读，也就是可能读取到其他会话中未提交事务修改的数据<br>  2).提交读(Read Committed)：只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)<br>  3).可重复读(Repeated Read)：可重复读。在同一个事务内的查询都是事务开始时刻一致的，InnoDB默认级别。在SQL标准中，该隔离级别消除了不可重复读，但是还存在幻象读，但是innoDB解决了幻读<br>  4).串行读(Serializable)：完全串行化的读，每次读都需要获得表级共享锁，读写相互都会阻塞<br>  5).使用数据库默认的隔离级别isolation &#x3D; Isolation.DEFAULT<br>    MySQL：mysql默认的事务处理级别是’REPEATABLE-READ’,也就是可重复读<br>    Oracle：oracle数据库支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别。默认系统事务隔离级别是READ COMMITTED,也就是读已提交</p><h4 id="28-为什么添加事务管理器"><a href="#28-为什么添加事务管理器" class="headerlink" title="28.为什么添加事务管理器"></a>28.为什么添加事务管理器</h4><p>  JDBC:  Connection   con.commit();   con.rollback();<br>  MyBatis:  SqlSession   sqlSession.commit();  sqlSession.rollback();<br>  Hibernate:  Session    session.commit();   session.rollback();</p><p>  事务管理器用来生成相应技术的连接+执行语句的对象.<br>  如果使用MyBatis框架,必须使用DataSourceTransactionManager类完成处理</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;transactionManager&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--因为事务必须关联数据库处理,所以要配置数据源--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;dataSource&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure><p>  项目中的所有事务,必须添加到业务逻辑层上.</p><h4 id="29-Spring事务的传播特性"><a href="#29-Spring事务的传播特性" class="headerlink" title="29.Spring事务的传播特性"></a>29.Spring事务的传播特性</h4><p>  多个事务之间的合并,互斥等都可以通过设置事务的传播特性来解决.<br>  常用<br>  PROPAGATION_REQUIRED：必被包含事务(增删改必用)<br>  PROPAGATION_REQUIRES_NEW：自己新开事务，不管之前是否有事务<br>  PROPAGATION_SUPPORTS：支持事务，如果加入的方法有事务，则支持事务，如果没有，不单开事务<br>  PROPAGATION_NEVER：不能运行中事务中，如果包在事务中，抛异常<br>  PROPAGATION_NOT_SUPPORTED：不支持事务，运行在非事务的环境<br>  不常用<br>  PROPAGATION_MANDATORY：必须包在事务中，没有事务则抛异常<br>  PROPAGATION_NESTED：嵌套事务</p><h4 id="30-为了测试传播特性改造项目"><a href="#30-为了测试传播特性改造项目" class="headerlink" title="30.为了测试传播特性改造项目"></a>30.为了测试传播特性改造项目</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span>  <span class="comment">//交给Spring去创建对象</span></span><br><span class="line"><span class="meta">@Transactional(propagation = Propagation.REQUIRED)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UsersServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">UsersService</span> &#123;    </span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    UsersMapper usersMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    AccountsService accountsService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">insert</span><span class="params">(Users users)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">num</span> <span class="operator">=</span> usersMapper.insert(users);</span><br><span class="line">        System.out.println(<span class="string">&quot;用户增加成功!num=&quot;</span>+num);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//调用帐户的增加操作,调用的帐户的业务逻辑层的功能</span></span><br><span class="line">        num = accountsService.save(<span class="keyword">new</span> <span class="title class_">Accounts</span>(<span class="number">300</span>,<span class="string">&quot;王五&quot;</span>,<span class="string">&quot;帐户好的呢!&quot;</span>));</span><br><span class="line">        <span class="keyword">return</span> num;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="31-声明式事务"><a href="#31-声明式事务" class="headerlink" title="31.声明式事务"></a>31.声明式事务</h4><p>  Spring非常有名的事务处理方式.声明式事务.<br>  要求项目中的方法命名有规范<br>  1)完成增加操作包含    add  save  insert  set<br>  2)更新操作包含   update   change  modify<br>  3)删除操作包含   delete   drop    remove  clear<br>  4)查询操作包含   select   find    search  get </p><p>  配置事务切面时可以使用通配符*来匹配所有方法<br>  <figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--添加事务管理器--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;transactionManager&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;dataSource&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--配置事务切面--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">tx:advice</span> <span class="attr">id</span>=<span class="string">&quot;myadvice&quot;</span> <span class="attr">transaction-manager</span>=<span class="string">&quot;transactionManager&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tx:attributes</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*select*&quot;</span> <span class="attr">read-only</span>=<span class="string">&quot;true&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*find*&quot;</span> <span class="attr">read-only</span>=<span class="string">&quot;true&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*search*&quot;</span> <span class="attr">read-only</span>=<span class="string">&quot;true&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*get*&quot;</span> <span class="attr">read-only</span>=<span class="string">&quot;true&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*insert*&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span> <span class="attr">no-rollback-for</span>=<span class="string">&quot;ArithmeticException&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*add*&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*save*&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span> <span class="attr">no-rollback-for</span>=<span class="string">&quot;ArithmeticException&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*set*&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*update*&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*change*&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*modify*&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*delete*&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*remove*&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*drop*&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*clear*&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;*&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;SUPPORTS&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tx:attributes</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">tx:advice</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--绑定切面和切入点--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">aop:config</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">aop:pointcut</span> <span class="attr">id</span>=<span class="string">&quot;mycut&quot;</span> <span class="attr">expression</span>=<span class="string">&quot;execution(* com.bjpowernode.service.impl.*.*(..))&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">aop:pointcut</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">aop:advisor</span>  <span class="attr">advice-ref</span>=<span class="string">&quot;myadvice&quot;</span> <span class="attr">pointcut-ref</span>=<span class="string">&quot;mycut&quot;</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></p><p>​    </p>]]></content>
    
    
      
      
    <summary type="html">&lt;h4 id=&quot;1-什么是Spring框架&quot;&gt;&lt;a href=&quot;#1-什么是Spring框架&quot; class=&quot;headerlink&quot; title=&quot;1.什么是Spring框架&quot;&gt;&lt;/a&gt;1.什么是Spring框架&lt;/h4&gt;&lt;p&gt;  它是一个容器.它是整合其它框架的框架.它的核心是</summary>
      
    
    
    
    <category term="JAVA" scheme="https://blog.bugjava.cn/categories/JAVA/"/>
    
    
    <category term="JAVA" scheme="https://blog.bugjava.cn/tags/JAVA/"/>
    
    <category term="Spring" scheme="https://blog.bugjava.cn/tags/Spring/"/>
    
  </entry>
  
  <entry>
    <title>Windows11优化</title>
    <link href="https://blog.bugjava.cn/post/good-win11/"/>
    <id>https://blog.bugjava.cn/post/good-win11/</id>
    <published>2022-03-24T10:49:00.000Z</published>
    <updated>2023-04-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Windows11优化"><a href="#Windows11优化" class="headerlink" title="Windows11优化"></a>Windows11优化</h1><h2 id="1-还原到windows10右键"><a href="#1-还原到windows10右键" class="headerlink" title="1.还原到windows10右键"></a>1.还原到windows10右键</h2><p>以管理员身份运行CMD，复制下列命令，按回车后即可恢复Win10的右键菜单</p><p><code>reg add &quot;HKCU\Software\Classes\CLSID\&#123;86ca1aa0-34aa-4e8b-a509-50c905bae2a2&#125;\InprocServer32&quot; /f /ve</code></p><p>需重启Windows资源管理器方能生效。</p><p>如果想恢复Win11菜单，就把添加的注册表项删掉。</p><p><code>reg delete &quot;HKCU\Software\Classes\CLSID\&#123;86ca1aa0-34aa-4e8b-a509-50c905bae2a2&#125;&quot; /f</code></p><h2 id="2-任务栏对齐方式调整"><a href="#2-任务栏对齐方式调整" class="headerlink" title="2.任务栏对齐方式调整"></a>2.任务栏对齐方式调整</h2><p>Win11默认将任务栏图标放在了中间，导致左右不平衡，十分难看。</p><p>在任务栏上右键任务栏设置，找到任务栏行为-任务栏对齐方式，调成“左”即可。</p>]]></content>
    
    
    <summary type="html">优化下win11的某些不好用的东西</summary>
    
    
    
    <category term="系统优化" scheme="https://blog.bugjava.cn/categories/%E7%B3%BB%E7%BB%9F%E4%BC%98%E5%8C%96/"/>
    
    
    <category term="OS" scheme="https://blog.bugjava.cn/tags/OS/"/>
    
  </entry>
  
  <entry>
    <title>JQuery 笔记（二）</title>
    <link href="https://blog.bugjava.cn/post/study_jquery_two/"/>
    <id>https://blog.bugjava.cn/post/study_jquery_two/</id>
    <published>2021-05-18T07:44:06.000Z</published>
    <updated>2023-04-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="JQuery-高级"><a href="#JQuery-高级" class="headerlink" title="JQuery 高级"></a>JQuery 高级</h2><pre><code>1. 动画1. 三种方式显示和隐藏元素1. 默认显示和隐藏方式1. show([speed,[easing],[fn]])1. 参数：1. speed：动画的速度。三个预定义的值(&quot;slow&quot;,&quot;normal&quot;, &quot;fast&quot;)或表示动画时长的毫秒数值(如：1000)2. easing：用来指定切换效果，默认是&quot;swing&quot;，可用参数&quot;linear&quot;* swing：动画执行时效果是 先慢，中间快，最后又慢* linear：动画执行时速度是匀速的3. fn：在动画完成时执行的函数，每个元素执行一次。2. hide([speed,[easing],[fn]])3. toggle([speed],[easing],[fn])2. 滑动显示和隐藏方式1. slideDown([speed],[easing],[fn])2. slideUp([speed,[easing],[fn]])3. slideToggle([speed],[easing],[fn])3. 淡入淡出显示和隐藏方式1. fadeIn([speed],[easing],[fn])2. fadeOut([speed],[easing],[fn])3. fadeToggle([speed,[easing],[fn]])2. 遍历1. js的遍历方式* for(初始化值;循环结束条件;步长)2. jq的遍历方式1. jq对象.each(callback)1. 语法：jquery对象.each(function(index,element)&#123;&#125;);* index:就是元素在集合中的索引* element：就是集合中的每一个元素对象* this：集合中的每一个元素对象2. 回调函数返回值：* true:如果当前function返回为false，则结束循环(break)。* false:如果当前function返回为true，则结束本次循环，继续下次循环(continue)2. $.each(object, [callback])3. for..of: jquery 3.0 版本之后提供的方式for(元素对象 of 容器对象)3. 事件绑定1. jquery标准的绑定方式* jq对象.事件方法(回调函数)；* 注：如果调用事件方法，不传递回调函数，则会触发浏览器默认行为。* 表单对象.submit();//让表单提交2. on绑定事件/off解除绑定* jq对象.on(&quot;事件名称&quot;,回调函数)* jq对象.off(&quot;事件名称&quot;)* 如果off方法不传递任何参数，则将组件上的所有事件全部解绑3. 事件切换：toggle* jq对象.toggle(fn1,fn2...)* 当单击jq对象对应的组件后，会执行fn1.第二次点击会执行fn2.....* 注意：1.9版本 .toggle() 方法删除,jQuery Migrate（迁移）插件可以恢复此功能。 &lt;script src=&quot;../js/jquery-migrate-1.0.0.js&quot; type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;4. 案例1. 广告显示和隐藏<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>广告的自动显示与隐藏<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">        <span class="selector-id">#content</span> &#123;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">height</span>: <span class="number">500px</span>;</span></span><br><span class="line"><span class="language-css">            <span class="attribute">background</span>: <span class="number">#999</span></span></span><br><span class="line"><span class="language-css">        &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--引入jquery--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">src</span>=<span class="string">&quot;../js/jquery-3.3.1.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">/*</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">            需求：</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">                1. 当页面加载完，3秒后。自动显示广告</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">                2. 广告显示5秒后，自动消失。</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript"></span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">            分析：</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">                1. 使用定时器来完成。setTimeout (执行一次定时器)</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">                2. 分析发现JQuery的显示和隐藏动画效果其实就是控制display</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">                3. 使用  show/hide方法来完成广告的显示</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">         */</span></span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//入口函数，在页面加载完成之后，定义定时器，调用这两个方法</span></span></span><br><span class="line"><span class="language-javascript">        $(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//定义定时器，调用adShow方法 3秒后执行一次</span></span></span><br><span class="line"><span class="language-javascript">            <span class="built_in">setTimeout</span>(adShow, <span class="number">3000</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//定义定时器，调用adHide方法，8秒后执行一次</span></span></span><br><span class="line"><span class="language-javascript">            <span class="built_in">setTimeout</span>(adHide, <span class="number">8000</span>);</span></span><br><span class="line"><span class="language-javascript">        &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//显示广告</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">function</span> <span class="title function_">adShow</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//获取广告div，调用显示方法</span></span></span><br><span class="line"><span class="language-javascript">            $(<span class="string">&quot;#ad&quot;</span>).<span class="title function_">show</span>(<span class="string">&quot;slow&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">        &#125;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//隐藏广告</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">function</span> <span class="title function_">adHide</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//获取广告div，调用隐藏方法</span></span></span><br><span class="line"><span class="language-javascript">            $(<span class="string">&quot;#ad&quot;</span>).<span class="title function_">hide</span>(<span class="string">&quot;slow&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">        &#125;</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 广告DIV --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;ad&quot;</span> <span class="attr">style</span>=<span class="string">&quot;display: none;&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">style</span>=<span class="string">&quot;width:100%&quot;</span> <span class="attr">src</span>=<span class="string">&quot;../img/adv.jpg&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 下方正文部分 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;content&quot;</span>&gt;</span></span><br><span class="line">    正文部分</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>2. 抽奖<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>jquery案例之抽奖<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">src</span>=<span class="string">&quot;../js/jquery-3.3.1.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">language</span>=<span class="string">&#x27;javascript&#x27;</span> <span class="attr">type</span>=<span class="string">&#x27;text/javascript&#x27;</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">/*</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">            分析：</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">                1. 给开始按钮绑定单击事件</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">                    1.1 定义循环定时器</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">                    1.2 切换小相框的src属性</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">                        * 定义数组，存放图片资源路径</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">                        * 生成随机数。数组索引</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript"></span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">                2. 给结束按钮绑定单击事件</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">                    1.1 停止定时器</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">                    1.2 给大相框设置src属性</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript"></span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">         */</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">var</span> imgs = [<span class="string">&quot;../img/man00.jpg&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="string">&quot;../img/man01.jpg&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="string">&quot;../img/man02.jpg&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="string">&quot;../img/man03.jpg&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="string">&quot;../img/man04.jpg&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="string">&quot;../img/man05.jpg&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="string">&quot;../img/man06.jpg&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                    ];</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">var</span> startId;<span class="comment">//开始定时器的id</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">var</span> index;<span class="comment">//随机角标</span></span></span><br><span class="line"><span class="language-javascript">        $(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//处理按钮是否可以使用的效果</span></span></span><br><span class="line"><span class="language-javascript">            $(<span class="string">&quot;#startID&quot;</span>).<span class="title function_">prop</span>(<span class="string">&quot;disabled&quot;</span>,<span class="literal">false</span>);</span></span><br><span class="line"><span class="language-javascript">            $(<span class="string">&quot;#stopID&quot;</span>).<span class="title function_">prop</span>(<span class="string">&quot;disabled&quot;</span>,<span class="literal">true</span>);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">           <span class="comment">//1. 给开始按钮绑定单击事件</span></span></span><br><span class="line"><span class="language-javascript">            $(<span class="string">&quot;#startID&quot;</span>).<span class="title function_">click</span>(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="comment">// 1.1 定义循环定时器 20毫秒执行一次</span></span></span><br><span class="line"><span class="language-javascript">                startId = <span class="built_in">setInterval</span>(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="comment">//处理按钮是否可以使用的效果</span></span></span><br><span class="line"><span class="language-javascript">                    $(<span class="string">&quot;#startID&quot;</span>).<span class="title function_">prop</span>(<span class="string">&quot;disabled&quot;</span>,<span class="literal">true</span>);</span></span><br><span class="line"><span class="language-javascript">                    $(<span class="string">&quot;#stopID&quot;</span>).<span class="title function_">prop</span>(<span class="string">&quot;disabled&quot;</span>,<span class="literal">false</span>);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">                    <span class="comment">//1.2生成随机角标 0-6</span></span></span><br><span class="line"><span class="language-javascript">                    index = <span class="title class_">Math</span>.<span class="title function_">floor</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>() * <span class="number">7</span>);<span class="comment">//0.000--0.999 --&gt; * 7 --&gt; 0.0-----6.9999</span></span></span><br><span class="line"><span class="language-javascript">                    <span class="comment">//1.3设置小相框的src属性</span></span></span><br><span class="line"><span class="language-javascript">                    $(<span class="string">&quot;#img1ID&quot;</span>).<span class="title function_">prop</span>(<span class="string">&quot;src&quot;</span>,imgs[index]);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">                &#125;,<span class="number">20</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//2. 给结束按钮绑定单击事件</span></span></span><br><span class="line"><span class="language-javascript">            $(<span class="string">&quot;#stopID&quot;</span>).<span class="title function_">click</span>(<span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="comment">//处理按钮是否可以使用的效果</span></span></span><br><span class="line"><span class="language-javascript">                $(<span class="string">&quot;#startID&quot;</span>).<span class="title function_">prop</span>(<span class="string">&quot;disabled&quot;</span>,<span class="literal">false</span>);</span></span><br><span class="line"><span class="language-javascript">                $(<span class="string">&quot;#stopID&quot;</span>).<span class="title function_">prop</span>(<span class="string">&quot;disabled&quot;</span>,<span class="literal">true</span>);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">               <span class="comment">// 1.1 停止定时器</span></span></span><br><span class="line"><span class="language-javascript">                <span class="built_in">clearInterval</span>(startId);</span></span><br><span class="line"><span class="language-javascript">               <span class="comment">// 1.2 给大相框设置src属性</span></span></span><br><span class="line"><span class="language-javascript">                $(<span class="string">&quot;#img2ID&quot;</span>).<span class="title function_">prop</span>(<span class="string">&quot;src&quot;</span>,imgs[index]).<span class="title function_">hide</span>();</span></span><br><span class="line"><span class="language-javascript">                <span class="comment">//显示1秒之后</span></span></span><br><span class="line"><span class="language-javascript">                $(<span class="string">&quot;#img2ID&quot;</span>).<span class="title function_">show</span>(<span class="number">1000</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">        &#125;);</span></span><br><span class="line"><span class="language-javascript">          </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 小像框 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;border-style:dotted;width:160px;height:100px&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">id</span>=<span class="string">&quot;img1ID&quot;</span> <span class="attr">src</span>=<span class="string">&quot;../img/man00.jpg&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width:160px;height:100px&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 大像框 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span></span></span><br><span class="line"><span class="tag">        <span class="attr">style</span>=<span class="string">&quot;border-style:double;width:800px;height:500px;position:absolute;left:500px;top:10px&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">id</span>=<span class="string">&quot;img2ID&quot;</span> <span class="attr">src</span>=<span class="string">&quot;../img/man00.jpg&quot;</span> <span class="attr">width</span>=<span class="string">&quot;800px&quot;</span> <span class="attr">height</span>=<span class="string">&quot;500px&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 开始按钮 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span></span></span><br><span class="line"><span class="tag">        <span class="attr">id</span>=<span class="string">&quot;startID&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">type</span>=<span class="string">&quot;button&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">value</span>=<span class="string">&quot;点击开始&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">style</span>=<span class="string">&quot;width:150px;height:150px;font-size:22px&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 停止按钮 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">input</span></span></span><br><span class="line"><span class="tag">        <span class="attr">id</span>=<span class="string">&quot;stopID&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">type</span>=<span class="string">&quot;button&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">value</span>=<span class="string">&quot;点击停止&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">style</span>=<span class="string">&quot;width:150px;height:150px;font-size:22px&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>5. 插件：增强JQuery的功能1. 实现方式：1. $.fn.extend(object) * 增强通过Jquery获取的对象的功能  $(&quot;#id&quot;)2. $.extend(object)* 增强JQeury对象自身的功能  $/jQuery</code></pre>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;JQuery-高级&quot;&gt;&lt;a href=&quot;#JQuery-高级&quot; class=&quot;headerlink&quot; title=&quot;JQuery 高级&quot;&gt;&lt;/a&gt;JQuery 高级&lt;/h2&gt;&lt;pre&gt;&lt;code&gt;1. 动画
	1. 三种方式显示和隐藏元素
		1. 默认显示和隐藏</summary>
      
    
    
    
    <category term="jQuery" scheme="https://blog.bugjava.cn/categories/jQuery/"/>
    
    
    <category term="笔记" scheme="https://blog.bugjava.cn/tags/%E7%AC%94%E8%AE%B0/"/>
    
    <category term="jQuery" scheme="https://blog.bugjava.cn/tags/jQuery/"/>
    
  </entry>
  
  <entry>
    <title>JQuery 笔记（一）</title>
    <link href="https://blog.bugjava.cn/post/study_jquery_one/"/>
    <id>https://blog.bugjava.cn/post/study_jquery_one/</id>
    <published>2021-05-16T11:58:54.000Z</published>
    <updated>2023-04-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="JQuery-基础："><a href="#JQuery-基础：" class="headerlink" title="JQuery 基础："></a>JQuery 基础：</h2><pre><code>1. 概念： 一个JavaScript框架。简化JS开发* jQuery是一个快速、简洁的JavaScript框架，是继Prototype之后又一个优秀的JavaScript代码库（或JavaScript框架）。jQuery设计的宗旨是“write Less，Do More”，即倡导写更少的代码，做更多的事情。它封装JavaScript常用的功能代码，提供一种简便的JavaScript设计模式，优化HTML文档操作、事件处理、动画设计和Ajax交互。* JavaScript框架：本质上就是一些js文件，封装了js的原生代码而已3. JQuery对象和JS对象区别与转换1. JQuery对象在操作时，更加方便。    2. JQuery对象和js对象方法不通用的.    3. 两者相互转换        * jq -- &gt; js : jq对象[索引] 或者 jq对象.get(索引)        * js -- &gt; jq : $(js对象)4. 选择器：筛选具有相似特征的元素(标签)1. 基本操作学习：1. 事件绑定//1.获取b1按钮            $(&quot;#b1&quot;).click(function()&#123;                alert(&quot;abc&quot;);            &#125;);2. 入口函数 $(function () &#123;               &#125;); window.onload  和 $(function) 区别                 * window.onload 只能定义一次,如果定义多次，后边的会将前边的覆盖掉                 * $(function)可以定义多次的。3. 样式控制：css方法 // $(&quot;#div1&quot;).css(&quot;background-color&quot;,&quot;red&quot;);      $(&quot;#div1&quot;).css(&quot;backgroundColor&quot;,&quot;pink&quot;);2. 分类1. 基本选择器1. 标签选择器（元素选择器）* 语法： $(&quot;html标签名&quot;) 获得所有匹配标签名称的元素2. id选择器 * 语法： $(&quot;#id的属性值&quot;) 获得与指定id属性值匹配的元素3. 类选择器* 语法： $(&quot;.class的属性值&quot;) 获得与指定的class属性值匹配的元素4. 并集选择器：* 语法： $(&quot;选择器1,选择器2....&quot;) 获取多个选择器选中的所有元素2. 层级选择器1. 后代选择器* 语法： $(&quot;A B &quot;) 选择A元素内部的所有B元素2. 子选择器* 语法： $(&quot;A &gt; B&quot;) 选择A元素内部的所有B子元素3. 属性选择器1. 属性名称选择器 * 语法： $(&quot;A[属性名]&quot;) 包含指定属性的选择器2. 属性选择器* 语法： $(&quot;A[属性名=&#39;值&#39;]&quot;) 包含指定属性等于指定值的选择器3. 复合属性选择器* 语法： $(&quot;A[属性名=&#39;值&#39;][]...&quot;) 包含多个属性条件的选择器4. 过滤选择器1. 首元素选择器 * 语法： :first 获得选择的元素中的第一个元素2. 尾元素选择器 * 语法： :last 获得选择的元素中的最后一个元素3. 非元素选择器* 语法： :not(selector) 不包括指定内容的元素4. 偶数选择器* 语法： :even 偶数，从 0 开始计数5. 奇数选择器* 语法： :odd 奇数，从 0 开始计数6. 等于索引选择器* 语法： :eq(index) 指定索引元素7. 大于索引选择器 * 语法： :gt(index) 大于指定索引元素8. 小于索引选择器 * 语法： :lt(index) 小于指定索引元素9. 标题选择器* 语法： :header 获得标题（h1~h6）元素，固定写法5. 表单过滤选择器1. 可用元素选择器 * 语法： :enabled 获得可用元素2. 不可用元素选择器 * 语法： :disabled 获得不可用元素3. 选中选择器 * 语法： :checked 获得单选/复选框选中的元素4. 选中选择器 * 语法： :selected 获得下拉框选中的元素5. DOM操作1. 内容操作1. html(): 获取/设置元素的标签体内容   &lt;a&gt;&lt;font&gt;内容&lt;/font&gt;&lt;/a&gt;  --&gt; &lt;font&gt;内容&lt;/font&gt;2. text(): 获取/设置元素的标签体纯文本内容   &lt;a&gt;&lt;font&gt;内容&lt;/font&gt;&lt;/a&gt; --&gt; 内容3. val()： 获取/设置元素的value属性值2. 属性操作1. 通用属性操作1. attr(): 获取/设置元素的属性2. removeAttr():删除属性3. prop():获取/设置元素的属性4. removeProp():删除属性* attr和prop区别？1. 如果操作的是元素的固有属性，则建议使用prop2. 如果操作的是元素自定义的属性，则建议使用attr2. 对class属性操作1. addClass():添加class属性值2. removeClass():删除class属性值3. toggleClass():切换class属性* toggleClass(&quot;one&quot;): * 判断如果元素对象上存在class=&quot;one&quot;，则将属性值one删除掉。  如果元素对象上不存在class=&quot;one&quot;，则添加4. css():3. CRUD操作:1. append():父元素将子元素追加到末尾* 对象1.append(对象2): 将对象2添加到对象1元素内部，并且在末尾2. prepend():父元素将子元素追加到开头* 对象1.prepend(对象2):将对象2添加到对象1元素内部，并且在开头3. appendTo():* 对象1.appendTo(对象2):将对象1添加到对象2内部，并且在末尾4. prependTo()：* 对象1.prependTo(对象2):将对象1添加到对象2内部，并且在开头5. after():添加元素到元素后边* 对象1.after(对象2)： 将对象2添加到对象1后边。对象1和对象2是兄弟关系6. before():添加元素到元素前边* 对象1.before(对象2)： 将对象2添加到对象1前边。对象1和对象2是兄弟关系7. insertAfter()* 对象1.insertAfter(对象2)：将对象2添加到对象1后边。对象1和对象2是兄弟关系8. insertBefore()* 对象1.insertBefore(对象2)： 将对象2添加到对象1前边。对象1和对象2是兄弟关系9. remove():移除元素* 对象.remove():将对象删除掉10. empty():清空元素的所有后代元素。* 对象.empty():将对象的后代元素全部清空，但是保留当前对象以及其属性节点</code></pre>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;JQuery-基础：&quot;&gt;&lt;a href=&quot;#JQuery-基础：&quot; class=&quot;headerlink&quot; title=&quot;JQuery 基础：&quot;&gt;&lt;/a&gt;JQuery 基础：&lt;/h2&gt;&lt;pre&gt;&lt;code&gt;1. 概念： 一个JavaScript框架。简化JS开发
	</summary>
      
    
    
    
    <category term="jQuery" scheme="https://blog.bugjava.cn/categories/jQuery/"/>
    
    
    <category term="笔记" scheme="https://blog.bugjava.cn/tags/%E7%AC%94%E8%AE%B0/"/>
    
    <category term="jQuery" scheme="https://blog.bugjava.cn/tags/jQuery/"/>
    
  </entry>
  
  <entry>
    <title>MySQL学习笔记2</title>
    <link href="https://blog.bugjava.cn/post/study_mysql_two/"/>
    <id>https://blog.bugjava.cn/post/study_mysql_two/</id>
    <published>2021-04-17T06:38:33.000Z</published>
    <updated>2023-04-08T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="DQL-查询语句"><a href="#DQL-查询语句" class="headerlink" title="DQL:查询语句"></a>DQL:查询语句</h1><pre><code>1. 排序查询* 语法：order by 子句* order by 排序字段1 排序方式1 ，  排序字段2 排序方式2...* 排序方式：* ASC：升序，默认的。* DESC：降序。* 注意：* 如果有多个排序条件，则当前边的条件值一样时，才会判断第二条件。2. 聚合函数：将一列数据作为一个整体，进行纵向的计算。1. count：计算个数1. 一般选择非空的列：主键2. count(*)2. max：计算最大值3. min：计算最小值4. sum：计算和5. avg：计算平均值* 注意：聚合函数的计算，排除null值。解决方案：1. 选择不包含非空的列进行计算2. IFNULL函数3. 分组查询:1. 语法：group by 分组字段；2. 注意：1. 分组之后查询的字段：分组字段、聚合函数2. where 和 having 的区别？1. where 在分组之前进行限定，如果不满足条件，则不参与分组。having在分组之后进行限定，如果不满足结果，则不会被查询出来2. where 后不可以跟聚合函数，having可以进行聚合函数的判断。-- 按照性别分组。分别查询男、女同学的平均分SELECT sex , AVG(math) FROM student GROUP BY sex;-- 按照性别分组。分别查询男、女同学的平均分,人数SELECT sex , AVG(math),COUNT(id) FROM student GROUP BY sex;--  按照性别分组。分别查询男、女同学的平均分,人数 要求：分数低于70分的人，不参与分组SELECT sex , AVG(math),COUNT(id) FROM student WHERE math &gt; 70 GROUP BY sex;--  按照性别分组。分别查询男、女同学的平均分,人数 要求：分数低于70分的人，不参与分组,分组之后。人数要大于2个人SELECT sex , AVG(math),COUNT(id) FROM student WHERE math &gt; 70 GROUP BY sex HAVING COUNT(id) &gt; 2;SELECT sex , AVG(math),COUNT(id) 人数 FROM student WHERE math &gt; 70 GROUP BY sex HAVING 人数 &gt; 2;4. 分页查询1. 语法：limit 开始的索引,每页查询的条数;2. 公式：开始的索引 = （当前的页码 - 1） * 每页显示的条数-- 每页显示3条记录 SELECT * FROM student LIMIT 0,3; -- 第1页SELECT * FROM student LIMIT 3,3; -- 第2页SELECT * FROM student LIMIT 6,3; -- 第3页3. limit 是一个MySQL&quot;方言&quot;</code></pre><h2 id="约束"><a href="#约束" class="headerlink" title="约束"></a>约束</h2><pre><code>* 概念： 对表中的数据进行限定，保证数据的正确性、有效性和完整性。* 分类：1. 主键约束：primary key2. 非空约束：not null3. 唯一约束：unique4. 外键约束：foreign key* 非空约束：not null，某一列的值不能为null1. 创建表时添加约束CREATE TABLE stu(id INT,NAME VARCHAR(20) NOT NULL -- name为非空);2. 创建表完后，添加非空约束ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;3. 删除name的非空约束ALTER TABLE stu MODIFY NAME VARCHAR(20);* 唯一约束：unique，某一列的值不能重复1. 注意：* 唯一约束可以有NULL值，但是只能有一条记录为null2. 在创建表时，添加唯一约束CREATE TABLE stu(id INT,phone_number VARCHAR(20) UNIQUE -- 手机号);3. 删除唯一约束ALTER TABLE stu DROP INDEX phone_number;4. 在表创建完后，添加唯一约束ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;* 主键约束：primary key。1. 注意：1. 含义：非空且唯一2. 一张表只能有一个字段为主键3. 主键就是表中记录的唯一标识2. 在创建表时，添加主键约束create table stu(id int primary key,-- 给id添加主键约束name varchar(20));3. 删除主键-- 错误 alter table stu modify id int ;ALTER TABLE stu DROP PRIMARY KEY;4. 创建完表后，添加主键ALTER TABLE stu MODIFY id INT PRIMARY KEY;5. 自动增长：1.  概念：如果某一列是数值类型的，使用 auto_increment 可以来完成值得自动增长2. 在创建表时，添加主键约束，并且完成主键自增长create table stu(id int primary key auto_increment,-- 给id添加主键约束name varchar(20));3. 删除自动增长ALTER TABLE stu MODIFY id INT;4. 添加自动增长ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;* 外键约束：foreign key,让表于表产生关系，从而保证数据的正确性。1. 在创建表时，可以添加外键* 语法：create table 表名(....外键列constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称));2. 删除外键ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;3. 创建表之后，添加外键ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);4. 级联操作1. 添加级联操作语法：ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE ON DELETE CASCADE  ;2. 分类：1. 级联更新：ON UPDATE CASCADE 2. 级联删除：ON DELETE CASCADE </code></pre><h2 id="数据库的设计"><a href="#数据库的设计" class="headerlink" title="数据库的设计"></a>数据库的设计</h2><pre><code>1. 多表之间的关系1. 分类：1. 一对一(了解)：* 如：人和身份证* 分析：一个人只有一个身份证，一个身份证只能对应一个人2. 一对多(多对一)：* 如：部门和员工* 分析：一个部门有多个员工，一个员工只能对应一个部门3. 多对多：* 如：学生和课程* 分析：一个学生可以选择很多门课程，一个课程也可以被很多学生选择2. 实现关系：1. 一对多(多对一)：* 如：部门和员工* 实现方式：在多的一方建立外键，指向一的一方的主键。2. 多对多：* 如：学生和课程* 实现方式：多对多关系实现需要借助第三张中间表。中间表至少包含两个字段，这两个字段作为第三张表的外键，分别指向两张表的主键3. 一对一(了解)：* 如：人和身份证* 实现方式：一对一关系实现，可以在任意一方添加唯一外键指向另一方的主键。3. 案例-- 创建旅游线路分类表 tab_category-- cid 旅游线路分类主键，自动增长-- cname 旅游线路分类名称非空，唯一，字符串 100CREATE TABLE tab_category (cid INT PRIMARY KEY AUTO_INCREMENT,cname VARCHAR(100) NOT NULL UNIQUE);-- 创建旅游线路表 tab_route/*rid 旅游线路主键，自动增长rname 旅游线路名称非空，唯一，字符串 100price 价格rdate 上架时间，日期类型cid 外键，所属分类*/CREATE TABLE tab_route(rid INT PRIMARY KEY AUTO_INCREMENT,rname VARCHAR(100) NOT NULL UNIQUE,price DOUBLE,rdate DATE,cid INT,FOREIGN KEY (cid) REFERENCES tab_category(cid));/*创建用户表 tab_useruid 用户主键，自增长username 用户名长度 100，唯一，非空password 密码长度 30，非空name 真实姓名长度 100birthday 生日sex 性别，定长字符串 1telephone 手机号，字符串 11email 邮箱，字符串长度 100*/CREATE TABLE tab_user (uid INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(100) UNIQUE NOT NULL,PASSWORD VARCHAR(30) NOT NULL,NAME VARCHAR(100),birthday DATE,sex CHAR(1) DEFAULT &#39;男&#39;,telephone VARCHAR(11),email VARCHAR(100));/*创建收藏表 tab_favoriterid 旅游线路 id，外键date 收藏时间uid 用户 id，外键rid 和 uid 不能重复，设置复合主键，同一个用户不能收藏同一个线路两次*/CREATE TABLE tab_favorite (rid INT, -- 线路idDATE DATETIME,uid INT, -- 用户id-- 创建复合主键PRIMARY KEY(rid,uid), -- 联合主键FOREIGN KEY (rid) REFERENCES tab_route(rid),FOREIGN KEY(uid) REFERENCES tab_user(uid));2. 数据库设计的范式* 概念：设计数据库时，需要遵循的一些规范。要遵循后边的范式要求，必须先遵循前边的所有范式要求设计关系数据库时，遵从不同的规范要求，设计出合理的关系型数据库，这些不同的规范要求被称为不同的范式，各种范式呈递次规范，越高的范式数据库冗余越小。目前关系数据库有六种范式：第一范式（1NF）、第二范式（2NF）、第三范式（3NF）、巴斯-科德范式（BCNF）、第四范式(4NF）和第五范式（5NF，又称完美范式）。* 分类：1. 第一范式（1NF）：每一列都是不可分割的原子数据项2. 第二范式（2NF）：在1NF的基础上，非码属性必须完全依赖于码（在1NF基础上消除非主属性对主码的部分函数依赖）* 几个概念：1. 函数依赖：A--&gt;B,如果通过A属性(属性组)的值，可以确定唯一B属性的值。则称B依赖于A例如：学号--&gt;姓名。  （学号，课程名称） --&gt; 分数2. 完全函数依赖：A--&gt;B， 如果A是一个属性组，则B属性值得确定需要依赖于A属性组中所有的属性值。例如：（学号，课程名称） --&gt; 分数3. 部分函数依赖：A--&gt;B， 如果A是一个属性组，则B属性值得确定只需要依赖于A属性组中某一些值即可。例如：（学号，课程名称） -- &gt; 姓名4. 传递函数依赖：A--&gt;B, B -- &gt;C . 如果通过A属性(属性组)的值，可以确定唯一B属性的值，在通过B属性（属性组）的值可以确定唯一C属性的值，则称 C 传递函数依赖于A例如：学号--&gt;系名，系名--&gt;系主任5. 码：如果在一张表中，一个属性或属性组，被其他所有属性所完全依赖，则称这个属性(属性组)为该表的码例如：该表中码为：（学号，课程名称）* 主属性：码属性组中的所有属性* 非主属性：除过码属性组的属性3. 第三范式（3NF）：在2NF基础上，任何非主属性不依赖于其它非主属性（在2NF基础上消除传递依赖）</code></pre><h2 id="数据库的备份和还原"><a href="#数据库的备份和还原" class="headerlink" title="数据库的备份和还原"></a>数据库的备份和还原</h2><pre><code>1. 命令行：* 语法：* 备份： mysqldump -u用户名 -p密码 数据库名称 &gt; 保存的路径* 还原：1. 登录数据库2. 创建数据库3. 使用数据库4. 执行文件。source 文件路径</code></pre>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;DQL-查询语句&quot;&gt;&lt;a href=&quot;#DQL-查询语句&quot; class=&quot;headerlink&quot; title=&quot;DQL:查询语句&quot;&gt;&lt;/a&gt;DQL:查询语句&lt;/h1&gt;&lt;pre&gt;&lt;code&gt;1. 排序查询
	* 语法：order by 子句
		* order by</summary>
      
    
    
    
    <category term="MySQL" scheme="https://blog.bugjava.cn/categories/MySQL/"/>
    
    
    <category term="MySQL" scheme="https://blog.bugjava.cn/tags/MySQL/"/>
    
    <category term="笔记" scheme="https://blog.bugjava.cn/tags/%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>MySQL学习笔记1</title>
    <link href="https://blog.bugjava.cn/post/study_mysql_one/"/>
    <id>https://blog.bugjava.cn/post/study_mysql_one/</id>
    <published>2021-04-16T04:06:24.000Z</published>
    <updated>2023-04-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="数据库的基本概念"><a href="#数据库的基本概念" class="headerlink" title="数据库的基本概念"></a>数据库的基本概念</h2><pre><code>1. 数据库的英文单词： DataBase 简称 ： DB2. 什么数据库？* 用于存储和管理数据的仓库。3. 数据库的特点：1. 持久化存储数据的。其实数据库就是一个文件系统2. 方便存储和管理数据3. 使用了统一的方式操作数据库 -- SQL</code></pre><h1 id="MySQL数据库软件"><a href="#MySQL数据库软件" class="headerlink" title="MySQL数据库软件"></a>MySQL数据库软件</h1><pre><code>1. 安装* 参见《MySQL基础.pdf》2. 卸载1. 去mysql的安装目录找到my.ini文件* 复制 datadir=&quot;C:/ProgramData/MySQL/MySQL Server 5.5/Data/&quot;2. 卸载MySQL3. 删除C:/ProgramData目录下的MySQL文件夹。3. 配置* MySQL服务启动1. 手动。2. cmd--&gt; services.msc 打开服务的窗口3. 使用管理员打开cmd* net start mysql : 启动mysql的服务* net stop mysql:关闭mysql服务* MySQL登录1. mysql -uroot -p密码2. mysql -hip -uroot -p连接目标的密码3. mysql --host=ip --user=root --password=连接目标的密码* MySQL退出1. exit2. quit* MySQL目录结构1. MySQL安装目录：basedir=&quot;D:/develop/MySQL/&quot;* 配置文件 my.ini2. MySQL数据目录：datadir=&quot;C:/ProgramData/MySQL/MySQL Server 5.5/Data/&quot;* 几个概念* 数据库：文件夹* 表：文件* 数据：数据</code></pre><h1 id="SQL"><a href="#SQL" class="headerlink" title="SQL"></a>SQL</h1><pre><code>1.什么是SQL？Structured Query Language：结构化查询语言其实就是定义了操作所有关系型数据库的规则。每一种数据库操作的方式存在不一样的地方，称为“方言”。2.SQL通用语法1. SQL 语句可以单行或多行书写，以分号结尾。2. 可使用空格和缩进来增强语句的可读性。3. MySQL 数据库的 SQL 语句不区分大小写，关键字建议使用大写。4. 3 种注释* 单行注释: -- 注释内容 或 # 注释内容(mysql 特有) * 多行注释: /* 注释 */3. SQL分类1) DDL(Data Definition Language)数据定义语言用来定义数据库对象：数据库，表，列等。关键字：create, drop,alter 等2) DML(Data Manipulation Language)数据操作语言用来对数据库中表的数据进行增删改。关键字：insert, delete, update 等3) DQL(Data Query Language)数据查询语言用来查询数据库中表的记录(数据)。关键字：select, where 等4) DCL(Data Control Language)数据控制语言(了解)用来定义数据库的访问权限和安全级别，及创建用户。关键字：GRANT， REVOKE 等</code></pre><h2 id="DDL-操作数据库、表"><a href="#DDL-操作数据库、表" class="headerlink" title="DDL:操作数据库、表"></a>DDL:操作数据库、表</h2><pre><code>1. 操作数据库：CRUD1. C(Create):创建* 创建数据库：* create database 数据库名称;* 创建数据库，判断不存在，再创建：* create database if not exists 数据库名称;* 创建数据库，并指定字符集* create database 数据库名称 character set 字符集名;* 练习： 创建db4数据库，判断是否存在，并制定字符集为gbk* create database if not exists db4 character set gbk;2. R(Retrieve)：查询* 查询所有数据库的名称:* show databases;* 查询某个数据库的字符集:查询某个数据库的创建语句* show create database 数据库名称;3. U(Update):修改* 修改数据库的字符集* alter database 数据库名称 character set 字符集名称;4. D(Delete):删除* 删除数据库* drop database 数据库名称;* 判断数据库存在，存在再删除* drop database if exists 数据库名称;5. 使用数据库* 查询当前正在使用的数据库名称* select database();* 使用数据库* use 数据库名称;2. 操作表1. C(Create):创建1. 语法：create table 表名(列名1 数据类型1,列名2 数据类型2,....列名n 数据类型n);* 注意：最后一列，不需要加逗号（,）* 数据库类型：1. int：整数类型* age int,2. double:小数类型* score double(5,2)3. date:日期，只包含年月日，yyyy-MM-dd4. datetime:日期，包含年月日时分秒 yyyy-MM-dd HH:mm:ss5. timestamp:时间错类型包含年月日时分秒 yyyy-MM-dd HH:mm:ss* 如果将来不给这个字段赋值，或赋值为null，则默认使用当前的系统时间，来自动赋值6. varchar：字符串* name varchar(20):姓名最大20个字符* zhangsan 8个字符  张三 2个字符* 创建表create table student(id int,name varchar(32),age int ,score double(4,1),birthday date,insert_time timestamp);* 复制表：* create table 表名 like 被复制的表名;  2. R(Retrieve)：查询* 查询某个数据库中所有的表名称* show tables;* 查询表结构* desc 表名;3. U(Update):修改1. 修改表名alter table 表名 rename to 新的表名;2. 修改表的字符集alter table 表名 character set 字符集名称;3. 添加一列alter table 表名 add 列名 数据类型;4. 修改列名称 类型alter table 表名 change 列名 新列别 新数据类型;alter table 表名 modify 列名 新数据类型;5. 删除列alter table 表名 drop 列名;4. D(Delete):删除* drop table 表名;* drop table  if exists 表名 ;* 客户端图形化工具：SQLYog</code></pre><h2 id="DML：增删改表中数据"><a href="#DML：增删改表中数据" class="headerlink" title="DML：增删改表中数据"></a>DML：增删改表中数据</h2><pre><code>1. 添加数据：* 语法：* insert into 表名(列名1,列名2,...列名n) values(值1,值2,...值n);* 注意：1. 列名和值要一一对应。2. 如果表名后，不定义列名，则默认给所有列添加值insert into 表名 values(值1,值2,...值n);3. 除了数字类型，其他类型需要使用引号(单双都可以)引起来2. 删除数据：* 语法：* delete from 表名 [where 条件]* 注意：1. 如果不加条件，则删除表中所有记录。2. 如果要删除所有记录1. delete from 表名; -- 不推荐使用。有多少条记录就会执行多少次删除操作2. TRUNCATE TABLE 表名; -- 推荐使用，效率更高 先删除表，然后再创建一张一样的表。3. 修改数据：* 语法：* update 表名 set 列名1 = 值1, 列名2 = 值2,... [where 条件];* 注意：1. 如果不加任何条件，则会将表中所有记录全部修改。</code></pre><h2 id="DQL：查询表中的记录"><a href="#DQL：查询表中的记录" class="headerlink" title="DQL：查询表中的记录"></a>DQL：查询表中的记录</h2><pre><code>* select * from 表名;1. 语法：select字段列表from表名列表where条件列表group by分组字段having分组之后的条件order by排序limit分页限定2. 基础查询1. 多个字段的查询select 字段名1，字段名2... from 表名；* 注意：* 如果查询所有字段，则可以使用*来替代字段列表。2. 去除重复：* distinct3. 计算列* 一般可以使用四则运算计算一些列的值。（一般只会进行数值型的计算）* ifnull(表达式1,表达式2)：null参与的运算，计算结果都为null* 表达式1：哪个字段需要判断是否为null* 如果该字段为null后的替换值。4. 起别名：* as：as也可以省略3. 条件查询1. where子句后跟条件2. 运算符* &gt; 、&lt; 、&lt;= 、&gt;= 、= 、&lt;&gt;* BETWEEN...AND  * IN( 集合) * LIKE：模糊查询* 占位符：* _:单个任意字符* %：多个任意字符* IS NULL  * and  或 &amp;&amp;* or  或 || * not  或 !-- 查询年龄大于20岁SELECT * FROM student WHERE age &gt; 20;SELECT * FROM student WHERE age &gt;= 20;-- 查询年龄等于20岁SELECT * FROM student WHERE age = 20;-- 查询年龄不等于20岁SELECT * FROM student WHERE age != 20;SELECT * FROM student WHERE age &lt;&gt; 20;-- 查询年龄大于等于20 小于等于30SELECT * FROM student WHERE age &gt;= 20 &amp;&amp;  age &lt;=30;SELECT * FROM student WHERE age &gt;= 20 AND  age &lt;=30;SELECT * FROM student WHERE age BETWEEN 20 AND 30;-- 查询年龄22岁，18岁，25岁的信息SELECT * FROM student WHERE age = 22 OR age = 18 OR age = 25SELECT * FROM student WHERE age IN (22,18,25);-- 查询英语成绩为nullSELECT * FROM student WHERE english = NULL; -- 不对的。null值不能使用 = （!=） 判断SELECT * FROM student WHERE english IS NULL;-- 查询英语成绩不为nullSELECT * FROM student WHERE english  IS NOT NULL;-- 查询姓马的有哪些？ likeSELECT * FROM student WHERE NAME LIKE &#39;马%&#39;;-- 查询姓名第二个字是化的人SELECT * FROM student WHERE NAME LIKE &quot;_化%&quot;;-- 查询姓名是3个字的人SELECT * FROM student WHERE NAME LIKE &#39;___&#39;;-- 查询姓名中包含德的人            SELECT * FROM student WHERE NAME LIKE &#39;%德%&#39;;</code></pre><p>​</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;pre&gt;&lt;code&gt;1. 数据库的英文单词： DataBase 简称 ： DB
2. 什么数据库</summary>
      
    
    
    
    <category term="MySQL" scheme="https://blog.bugjava.cn/categories/MySQL/"/>
    
    
    <category term="MySQL" scheme="https://blog.bugjava.cn/tags/MySQL/"/>
    
    <category term="笔记" scheme="https://blog.bugjava.cn/tags/%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>Java学习路线图（完整详细2021版）</title>
    <link href="https://blog.bugjava.cn/post/java-study/"/>
    <id>https://blog.bugjava.cn/post/java-study/</id>
    <published>2021-02-10T02:31:37.000Z</published>
    <updated>2023-04-08T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Java零基础"><a href="#Java零基础" class="headerlink" title="Java零基础"></a><strong>Java零基础</strong></h2><p><img src="/images/java-study1.png"></p><p>推荐教程：</p><p>1、Java小白学习指南</p><p><a href="https://www.bilibili.com/video/BV1wv411B7q3">https://www.bilibili.com/video/BV1wv411B7q3</a></p><p>2、Java零基础</p><p><a href="https://www.bilibili.com/video/BV1Rx411876f">https://www.bilibili.com/video/BV1Rx411876f</a></p><h2 id="数据库"><a href="#数据库" class="headerlink" title="数据库"></a><strong>数据库</strong></h2><p>推荐教程：</p><p>1、MySQL数据库</p><p><a href="https://www.bilibili.com/video/BV1fx411X7BD">https://www.bilibili.com/video/BV1fx411X7BD</a></p><p>2、JDBC</p><p><a href="https://www.bilibili.com/video/BV1Bt41137iB">https://www.bilibili.com/video/BV1Bt41137iB</a></p><p>3、Oracle（有兴趣的可以学习一下）</p><p><a href="https://www.bilibili.com/video/BV1kx411s71n">https://www.bilibili.com/video/BV1kx411s71n</a></p><h2 id="Web前端"><a href="#Web前端" class="headerlink" title="Web前端"></a><strong>Web前端</strong></h2><p><img src="/images/java-study2.png"></p><p><img src="/images/java-study3.png"></p><p>教程链接：</p><p>1、HTML</p><p><a href="https://www.bilibili.com/video/BV11t411K74Q">https://www.bilibili.com/video/BV11t411K74Q</a></p><p>2、CSS</p><p><a href="https://www.bilibili.com/video/BV1tt411M7Vj">https://www.bilibili.com/video/BV1tt411M7Vj</a></p><p>3、JavaScript</p><p><a href="https://www.bilibili.com/video/BV1Ft411N7R3">https://www.bilibili.com/video/BV1Ft411N7R3</a></p><h2 id="JavaWeb"><a href="#JavaWeb" class="headerlink" title="JavaWeb"></a><strong>JavaWeb</strong></h2><p><img src="/images/java-study4.png"></p><p><img src="/images/java-study5.png"></p><p><img src="/images/java-study6.png"></p><p>教程链接：</p><p>1、JavaWeb【IDEA版本】</p><p><a href="https://www.bilibili.com/video/BV1Yz411B7Pk">https://www.bilibili.com/video/BV1Yz411B7Pk</a></p><p>2、JavaWeb【Eclipse经典版】</p><p><a href="https://www.bilibili.com/video/BV1Yz411B7Pk">https://www.bilibili.com/video/BV1Yz411B7Pk</a></p><h2 id="Web进阶"><a href="#Web进阶" class="headerlink" title="Web进阶"></a><strong>Web进阶</strong></h2><p><img src="/images/java-study7.png"></p><p>教程链接：</p><p>1、AJAX</p><p><a href="https://www.bilibili.com/video/BV15k4y167XM">https://www.bilibili.com/video/BV15k4y167XM</a></p><p>2、jQuery</p><p><a href="https://www.bilibili.com/video/BV1Jg4y1B7n4">https://www.bilibili.com/video/BV1Jg4y1B7n4</a></p><p>JavaWEB项目实战</p><p><img src="/images/java-study8.png"></p><p>教程链接：</p><p>1、SVN（路线图里没有写，但是我还是推荐，学习项目之前先看这个）</p><p><a href="https://www.bilibili.com/video/BV1ux411j7H2">https://www.bilibili.com/video/BV1ux411j7H2</a></p><p>2、EGOV项目（电子政务系统）路线图里没有但是感觉这个项目讲的真的很好就推荐了</p><p><a href="https://www.bilibili.com/video/BV194411c7SL">https://www.bilibili.com/video/BV194411c7SL</a></p><p>3、JDK动态代{过}{滤}理（学习CRM项目之前先看这个）</p><p><a href="https://www.bilibili.com/video/BV1HZ4y1p7F1">https://www.bilibili.com/video/BV1HZ4y1p7F1</a></p><p>4、Maven入门（这个学习项目必须提前要学习）</p><p><a href="https://www.bilibili.com/video/BV1dp4y1Q7Hf">https://www.bilibili.com/video/BV1dp4y1Q7Hf</a></p><p>5、CRM项目实战（学习之前建议先看看mybatis）</p><p><a href="https://www.bilibili.com/video/BV1fT4y1E7a6">https://www.bilibili.com/video/BV1fT4y1E7a6</a></p><p>6、Linux</p><p><a href="https://www.bilibili.com/video/BV1Li4y1V7pG">https://www.bilibili.com/video/BV1Li4y1V7pG</a></p><h2 id="后端框架"><a href="#后端框架" class="headerlink" title="后端框架"></a><strong>后端框架</strong></h2><p><img src="/images/java-study9.png"></p><p><img src="/images/java-study10.png"></p><p><img src="/images/java-study11.png"></p><p>教程链接：</p><p>1、Mybatis【IDEA版】</p><p><a href="https://www.bilibili.com/video/BV185411s7Ry">https://www.bilibili.com/video/BV185411s7Ry</a></p><p>2、Spring【IDEA版】</p><p><a href="https://www.bilibili.com/video/BV1nz4y1d7uy">https://www.bilibili.com/video/BV1nz4y1d7uy</a></p><p>3、SpringMVC【IDEA版】</p><p><a href="https://www.bilibili.com/video/BV1sk4y167pD">https://www.bilibili.com/video/BV1sk4y167pD</a></p><p>4、典藏版SSM（Eclipse全套）</p><p><a href="https://www.bilibili.com/video/BV1Ug4y1i7W7">https://www.bilibili.com/video/BV1Ug4y1i7W7</a></p><p>5、SSH框架全套【如果有时间的话可以选择性的学习一下】</p><p><a href="https://www.bilibili.com/video/BV1uT4y1g7Qo">https://www.bilibili.com/video/BV1uT4y1g7Qo</a></p><h2 id="高端技术"><a href="#高端技术" class="headerlink" title="高端技术"></a><strong>高端技术</strong></h2><p>教程链接：</p><p>1、Dubbo</p><p><a href="https://www.bilibili.com/video/BV1Sk4y197eD">https://www.bilibili.com/video/BV1Sk4y197eD</a></p><p>2、Redis</p><p><a href="https://www.bilibili.com/video/BV1Uz4y1X72A">https://www.bilibili.com/video/BV1Uz4y1X72A</a></p><p>3、Maven进阶</p><p><a href="https://www.bilibili.com/video/BV1kg4y187td">https://www.bilibili.com/video/BV1kg4y187td</a></p><p>4、springboot</p><p><a href="https://www.bilibili.com/video/BV1PZ4y1j7QK">https://www.bilibili.com/video/BV1PZ4y1j7QK</a></p><p>5、Nginx</p><p><a href="https://www.bilibili.com/video/BV11V411C7r9">https://www.bilibili.com/video/BV11V411C7r9</a></p><p>6、SpringSession</p><p><a href="https://www.bilibili.com/video/BV1iK411p7dZ">https://www.bilibili.com/video/BV1iK411p7dZ</a></p><p>7、FastDFS</p><p><a href="https://www.bilibili.com/video/BV1ta4y1v7Kw">https://www.bilibili.com/video/BV1ta4y1v7Kw</a></p><p>8、RabbitMQ</p><p><a href="https://www.bilibili.com/video/BV1Ap4y1D7tU">https://www.bilibili.com/video/BV1Ap4y1D7tU</a></p><p>9、SpringCloud</p><p><a href="https://www.bilibili.com/video/BV1aC4y1p7Qi">https://www.bilibili.com/video/BV1aC4y1p7Qi</a></p><p>10、SpringCloudAlibaba</p><p><a href="https://www.bilibili.com/video/BV1nK4y1j7gL">https://www.bilibili.com/video/BV1nK4y1j7gL</a></p><p>11、Docker</p><p><a href="https://www.bilibili.com/video/BV1QA411L7B5">https://www.bilibili.com/video/BV1QA411L7B5</a></p><p>12、K8S</p><p><a href="https://www.bilibili.com/video/BV1KU4y147g3">https://www.bilibili.com/video/BV1KU4y147g3</a></p><p>13、MySQL集群</p><p><a href="https://www.bilibili.com/video/BV1Rg4y1i7VR">https://www.bilibili.com/video/BV1Rg4y1i7VR</a></p><p>14、Mycat</p><p><a href="https://www.bilibili.com/video/BV1gK4y1b7iU">https://www.bilibili.com/video/BV1gK4y1b7iU</a></p><p>15、Shiro</p><p><a href="https://www.bilibili.com/video/BV14T4y1g75M">https://www.bilibili.com/video/BV14T4y1g75M</a></p><p>16、互联网大型电商项目实战</p><p><a href="https://www.bilibili.com/video/BV1RQ4y1K7Pq">https://www.bilibili.com/video/BV1RQ4y1K7Pq</a></p><p><img src="/images/java-study12.png"></p><p><img src="/images/java-study13.png"></p><p>转载自：<a href="https://www.52pojie.cn/thread-1354997-1-1.html">https://www.52pojie.cn/thread-1354997-1-1.html</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Java零基础&quot;&gt;&lt;a href=&quot;#Java零基础&quot; class=&quot;headerlink&quot; title=&quot;Java零基础&quot;&gt;&lt;/a&gt;&lt;strong&gt;Java零基础&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;/images/java-study1.png</summary>
      
    
    
    
    <category term="JAVA" scheme="https://blog.bugjava.cn/categories/JAVA/"/>
    
    
    <category term="JAVA" scheme="https://blog.bugjava.cn/tags/JAVA/"/>
    
    <category term="学习路线" scheme="https://blog.bugjava.cn/tags/%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF/"/>
    
  </entry>
  
  <entry>
    <title>力扣做题笔记（2）：一维数组的动态和</title>
    <link href="https://blog.bugjava.cn/post/leetcode-2/"/>
    <id>https://blog.bugjava.cn/post/leetcode-2/</id>
    <published>2021-02-06T15:14:47.000Z</published>
    <updated>2023-04-08T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h3 id="题目"><a href="#题目" class="headerlink" title="题目"></a>题目</h3><p>给你一个数组 <code>nums</code> 。数组「动态和」的计算公式为：<code>runningSum[i] = sum(nums[0]…nums[i])</code> 。</p><p>请返回 <code>nums</code> 的动态和。</p><p>示例 ：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">输入：nums = [<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">输出：[<span class="number">1</span>,<span class="number">3</span>,<span class="number">6</span>,<span class="number">10</span>]</span><br><span class="line">解释：动态和计算过程为 [<span class="number">1</span>, <span class="number">1</span>+<span class="number">2</span>, <span class="number">1</span>+<span class="number">2</span>+<span class="number">3</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><p>来源：力扣（LeetCode）<br>链接：<a href="https://leetcode-cn.com/problems/running-sum-of-1d-array">https://leetcode-cn.com/problems/running-sum-of-1d-array</a></p><h3 id="解题思路"><a href="#解题思路" class="headerlink" title="解题思路"></a>解题思路</h3><p>双层for循环，第一个循环出数组的个数，第二个循环出每个数的和。</p><h3 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Solution</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span>[] runningSum(<span class="type">int</span>[] nums) &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">sum</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="type">int</span>[] Arrays = <span class="keyword">new</span> <span class="title class_">int</span>[nums.length];</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; nums.length; i++) &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">a</span> <span class="operator">=</span> <span class="number">0</span>; a &lt;= (i); a++) &#123;</span><br><span class="line">                sum = sum + nums[a];</span><br><span class="line">                Arrays[i] = sum;</span><br><span class="line">            &#125;</span><br><span class="line">            sum = <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> Arrays;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;题目&quot;&gt;&lt;a href=&quot;#题目&quot; class=&quot;headerlink&quot; title=&quot;题目&quot;&gt;&lt;/a&gt;题目&lt;/h3&gt;&lt;p&gt;给你一个数组 &lt;code&gt;nums&lt;/code&gt; 。数组「动态和」的计算公式为：&lt;code&gt;runningSum[i] = sum(nums</summary>
      
    
    
    
    <category term="JAVA" scheme="https://blog.bugjava.cn/categories/JAVA/"/>
    
    
    <category term="JAVA" scheme="https://blog.bugjava.cn/tags/JAVA/"/>
    
    <category term="力扣" scheme="https://blog.bugjava.cn/tags/%E5%8A%9B%E6%89%A3/"/>
    
    <category term="做题笔记" scheme="https://blog.bugjava.cn/tags/%E5%81%9A%E9%A2%98%E7%AC%94%E8%AE%B0/"/>
    
    <category term="数组" scheme="https://blog.bugjava.cn/tags/%E6%95%B0%E7%BB%84/"/>
    
  </entry>
  
  <entry>
    <title>力扣做题笔记（1）：重新排列数组</title>
    <link href="https://blog.bugjava.cn/post/leetcode-1/"/>
    <id>https://blog.bugjava.cn/post/leetcode-1/</id>
    <published>2021-02-06T15:06:47.000Z</published>
    <updated>2023-04-08T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h3 id="题目"><a href="#题目" class="headerlink" title="题目"></a>题目</h3><p>给你一个数组 <code>nums</code> ，数组中有 <code>2n</code> 个元素，按 <code>[x1,x2,...,xn,y1,y2,...,yn]</code> 的格式排列。</p><p>请你将数组按 <code>[x1,y1,x2,y2,...,xn,yn]</code> 格式重新排列，返回重排后的数组。</p><p>示例 ：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">输入：nums = [2,5,1,3,4,7], n = 3</span><br><span class="line">输出：[2,3,5,4,1,7] </span><br><span class="line">解释：由于 x1=2, x2=5, x3=1, y1=3, y2=4, y3=7 ，所以答案为 [2,3,5,4,1,7]</span><br></pre></td></tr></table></figure><p>来源：力扣（LeetCode）<br>链接：<a href="https://leetcode-cn.com/problems/shuffle-the-array">https://leetcode-cn.com/problems/shuffle-the-array</a></p><h3 id="解题思路"><a href="#解题思路" class="headerlink" title="解题思路"></a>解题思路</h3><ol><li><p>先通过循环把x和y分别给两个数组。</p></li><li><p>在把两个数组交叉合并</p></li></ol><h3 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span>[] shuffle(<span class="type">int</span>[] nums, <span class="type">int</span> n) &#123;</span><br><span class="line">        <span class="type">int</span>[] Array = <span class="keyword">new</span> <span class="title class_">int</span>[<span class="number">2</span> * n];</span><br><span class="line">        <span class="type">int</span>[] Arrayx = <span class="keyword">new</span> <span class="title class_">int</span>[n];</span><br><span class="line">        <span class="type">int</span>[] Arrayy = <span class="keyword">new</span> <span class="title class_">int</span>[n];</span><br><span class="line">        <span class="type">int</span> <span class="variable">a</span> <span class="operator">=</span> <span class="number">0</span>, b = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; Arrayx.length; i++) &#123;<span class="comment">//把数组的前n个给x数组</span></span><br><span class="line">            Arrayx[i] = nums[i];</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; Arrayy.length; i++) &#123;<span class="comment">//把数组的后n个给y数组</span></span><br><span class="line">            Arrayy[i] = nums[i+n];</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; Array.length; i++) &#123;<span class="comment">//把x和y数组交叉合并</span></span><br><span class="line">            <span class="keyword">if</span> (i % <span class="number">2</span> ==<span class="number">0</span>)&#123;</span><br><span class="line">                Array[i] = Arrayx[a++];</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                Array[i] = Arrayy[b++];</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> Array;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;题目&quot;&gt;&lt;a href=&quot;#题目&quot; class=&quot;headerlink&quot; title=&quot;题目&quot;&gt;&lt;/a&gt;题目&lt;/h3&gt;&lt;p&gt;给你一个数组 &lt;code&gt;nums&lt;/code&gt; ，数组中有 &lt;code&gt;2n&lt;/code&gt; 个元素，按 &lt;code&gt;[x1,x2,...,</summary>
      
    
    
    
    <category term="JAVA" scheme="https://blog.bugjava.cn/categories/JAVA/"/>
    
    
    <category term="JAVA" scheme="https://blog.bugjava.cn/tags/JAVA/"/>
    
    <category term="力扣" scheme="https://blog.bugjava.cn/tags/%E5%8A%9B%E6%89%A3/"/>
    
    <category term="做题笔记" scheme="https://blog.bugjava.cn/tags/%E5%81%9A%E9%A2%98%E7%AC%94%E8%AE%B0/"/>
    
    <category term="数组" scheme="https://blog.bugjava.cn/tags/%E6%95%B0%E7%BB%84/"/>
    
  </entry>
  
  <entry>
    <title>Jetbrains系列产品重置试用方法</title>
    <link href="https://blog.bugjava.cn/post/Jetbrains-eval-resetter/"/>
    <id>https://blog.bugjava.cn/post/Jetbrains-eval-resetter/</id>
    <published>2021-01-04T12:45:22.000Z</published>
    <updated>2021-05-30T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h1><blockquote><p>Jetbrains系列产品一个可以<strong>无限</strong>重置试用的插件</p></blockquote><span id="more"></span><p>Jetbrains的产品很多人都知道特别好用，可是他们的产品都是贵的离谱。</p><p>但是Jetbrains有一个很良心的地方，他会允许你试用<code>30</code>天以评估是否你真的需要为它而付费。</p><p>事实上有一款插件可以实现这个功能，你或许可以用它来重置一下试用时间。</p><p>如何安装？</p><h3 id="1-插件市场安装："><a href="#1-插件市场安装：" class="headerlink" title="1. 插件市场安装："></a>1. 插件市场安装：</h3><ul><li>在<code>Settings/Preferences...</code> -&gt; <code>Plugins</code> 内手动添加第三方插件仓库地址：<code>https://plugins.zhile.io</code></li><li>搜索：<code>IDE Eval Reset</code>插件进行安装。如果搜索不到请注意是否做好了上一步？网络是否通畅？</li><li>插件会提示安装成功。</li></ul><h3 id="2-下载安装："><a href="#2-下载安装：" class="headerlink" title="2. 下载安装："></a>2. 下载安装：</h3><ul><li>请到 <a href="https://gitee.com/pengzhile/ide-eval-resetter">仓库地址</a> 获取连接，下载插件的<code>zip</code>包（macOS可能会自动解压，然后把<code>zip</code>包丢进回收站）</li><li>通常可以直接把<code>zip</code>包拖进IDE的窗口来进行插件的安装。如果无法拖动安装，你可以在<code>Settings/Preferences...</code> -&gt; <code>Plugins</code> 里手动安装插件（<code>Install Plugin From Disk...</code>）</li><li>插件会提示安装成功。</li></ul><p>如何使用？</p><ol><li></li></ol><ul><li>如果IDE没有打开项目，在<code>Welcome</code>界面点击菜单：<code>Get Help</code> -&gt; <code>Eval Reset</code></li><li>如果IDE打开了项目，点击菜单：<code>Help</code> -&gt; <code>Eval Reset</code></li></ul><ol start="2"><li></li></ol><ul><li>按钮：<code>Reload</code> 用来刷新界面上的显示信息。</li><li>按钮：<code>Reset</code> 点击会询问是否重置试用信息并<strong>重启IDE</strong>。选择<code>Yes</code>则执行重置操作并<strong>重启IDE生效</strong>，选择<code>No</code>则什么也不做。（此为手动重置方式）</li><li>勾选项：<code>Auto reset before per restart</code> 如果勾选了，则自勾选后<strong>每次重启&#x2F;退出IDE时会自动重置试用信息</strong>，你无需做额外的事情。（此为自动重置方式）</li></ul><p>如何更新？</p><ul><li>点击IDE的<code>Check for Updates...</code> 菜单手动检测IDE和所安装插件的更新。如果本插件有更新，你会收到提示看到更新日志，自行选择是否更新。</li></ul><h2 id="支持的产品"><a href="#支持的产品" class="headerlink" title="支持的产品"></a>支持的产品</h2><ul><li><strong>IntelliJ IDEA</strong></li><li><strong>AppCode</strong></li><li><strong>CLion</strong></li><li><strong>DataGrip</strong></li><li><strong>GoLand</strong></li><li><strong>PhpStorm</strong></li><li><strong>PyCharm</strong></li><li><strong>Rider</strong></li><li><strong>RubyMine</strong></li><li><strong>WebStorm</strong></li></ul><p>详细请看 <a href="https://zhile.io/2020/11/18/jetbrains-eval-reset.html">传送门</a></p>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;介绍&quot;&gt;&lt;a href=&quot;#介绍&quot; class=&quot;headerlink&quot; title=&quot;介绍&quot;&gt;&lt;/a&gt;介绍&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;Jetbrains系列产品一个可以&lt;strong&gt;无限&lt;/strong&gt;重置试用的插件&lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    <category term="Jetbrains" scheme="https://blog.bugjava.cn/categories/Jetbrains/"/>
    
    
    <category term="Jetbrains" scheme="https://blog.bugjava.cn/tags/Jetbrains/"/>
    
  </entry>
  
  <entry>
    <title>解析神器xpath使用教程</title>
    <link href="https://blog.bugjava.cn/post/xpath-use/"/>
    <id>https://blog.bugjava.cn/post/xpath-use/</id>
    <published>2020-05-02T01:19:43.000Z</published>
    <updated>2023-04-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h1><blockquote><p><strong>XPath</strong> (XML Path Language) 是一门在 HTML\XML 文档中查找信息的<strong>语言</strong>，可用来在 HTML\XML 文档中对<strong>元素和属性进行遍历</strong>。</p></blockquote><span id="more"></span><h2 id="为什么要学习xpath和parsel"><a href="#为什么要学习xpath和parsel" class="headerlink" title="为什么要学习xpath和parsel"></a>为什么要学习xpath和parsel</h2><ul><li>parsel是一款高性能的 Python HTML&#x2F;XML 解析器。</li><li>将字符串转化为Selector对象,Selector对象具有xpath的方法,返回结果的列表，能够接受bytes类型的数据和str类型的数据。</li><li>我们可以利用XPath，来快速的定位特定元素以及获取节点信息</li></ul><h2 id="节点"><a href="#节点" class="headerlink" title="节点"></a>节点</h2><blockquote><p>每个html的标签我们都称之为节点。（根节点、子节点、同级节点）</p></blockquote><p><img src="/../../img/jdgx.png" alt="节点的关系"></p><h1 id="xpath说明"><a href="#xpath说明" class="headerlink" title="xpath说明"></a>xpath说明</h1><blockquote><p><strong>XPath</strong> 使用路径表达式来选取 XML 文档中的节点或者节点集。</p></blockquote><h2 id="xpath表达式"><a href="#xpath表达式" class="headerlink" title="xpath表达式"></a>xpath表达式</h2><table><thead><tr><th align="center">表达式</th><th>描述</th></tr></thead><tbody><tr><td align="center">nodename</td><td>选中该元素。</td></tr><tr><td align="center">&#x2F;</td><td>从根节点选取、或者是元素和元素间的过渡。</td></tr><tr><td align="center">&#x2F;&#x2F;</td><td>从匹配选择的当前节点选择文档中的节点，而不考虑它们的位置。跨节点获取标签</td></tr><tr><td align="center">.</td><td>选取当前节点。</td></tr><tr><td align="center">..</td><td>选取当前节点的父节点。</td></tr><tr><td align="center">@</td><td>选取属性。</td></tr><tr><td align="center">text()</td><td>选取文本。</td></tr></tbody></table><ul><li>选取未知节点</li></ul><table><thead><tr><th>通配符</th><th>描述</th></tr></thead><tbody><tr><td>*</td><td>匹配任何元素节点。</td></tr><tr><td>@*</td><td>匹配任何属性节点。</td></tr><tr><td>node()</td><td>匹配任何类型的节点。</td></tr></tbody></table><table><thead><tr><th>&#x2F;div&#x2F;*</th><th>选取 div元素的所有子元素。</th></tr></thead><tbody><tr><td>&#x2F;&#x2F;*</td><td>选取文档中的所有元素。</td></tr><tr><td>&#x2F;&#x2F;title[@*]</td><td>选取所有带有属性的 title 元素。</td></tr></tbody></table><h1 id="xpath的使用方法"><a href="#xpath的使用方法" class="headerlink" title="xpath的使用方法"></a>xpath的使用方法</h1><p>要用到parsel模块</p><p>import parsel</p><p>使用xpath的前提是 具有xpath方法  –&gt; Selector对象</p><p>提取到的数据返回一个列表</p><p>转换数据类型方法</p><figure class="highlight plaintext"><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">data = parsel.Selector(html_str).extract()  # parsel能够把缺失的html标签补充完成</span><br><span class="line">data = parsel.Selector(html_str)  # parsel能够把缺失的html标签补充完成</span><br></pre></td></tr></table></figure><h1 id="xpath表达式说明"><a href="#xpath表达式说明" class="headerlink" title="xpath表达式说明"></a>xpath表达式说明</h1><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">ul</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&quot;item-1&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;link1.html&quot;</span>&gt;</span>第一个<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">li</span>&gt;</span> </span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&quot;item-2&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;link2.html&quot;</span>&gt;</span>第二个<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">li</span>&gt;</span> </span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&quot;item-3&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;link3.html&quot;</span>&gt;</span>第三个<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">li</span>&gt;</span> </span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&quot;item-4&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;link4.html&quot;</span>&gt;</span>第四个<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">li</span>&gt;</span> </span><br><span class="line"> </span><br><span class="line"><span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&quot;item-5&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;link5.html&quot;</span>&gt;</span>第五个<span class="tag">&lt;/<span class="name">a</span>&gt;</span> </span><br><span class="line"><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><ol><li>从根节点开始，获取所有 a 标签</li></ol><figure class="highlight python"><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">result = data.xpath(<span class="string">&#x27;/html/body/div/ul/li/a&#x27;</span>).extract()</span><br><span class="line"><span class="built_in">print</span>(result)</span><br></pre></td></tr></table></figure><ol start="2"><li>跨节点获取所有 a 标签</li></ol><figure class="highlight python"><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">result = data.xpath(<span class="string">&#x27;//a&#x27;</span>).extract()</span><br><span class="line"><span class="built_in">print</span>(result)</span><br></pre></td></tr></table></figure><ol start="3"><li>选取当前节点   使用场景：需要对选取的标签的下一级标签进行多次提取</li></ol><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></pre></td><td class="code"><pre><span class="line">result = data.xpath(<span class="string">&#x27;//ul&#x27;</span>)</span><br><span class="line">result2 = result.xpath(<span class="string">&#x27;./li&#x27;</span>).extract()</span><br><span class="line">result3 = result.xpath(<span class="string">&#x27;./li/a&#x27;</span>).extract()</span><br><span class="line"><span class="built_in">print</span>(result3)</span><br></pre></td></tr></table></figure><ol start="4"><li>选取当前节点的父节点,获取父节点的class属性值</li></ol><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">result = data.xpath(<span class="string">&#x27;//a&#x27;</span>)</span><br><span class="line">result4 = result.xpath(<span class="string">&#x27;../@class&#x27;</span>).extract()</span><br><span class="line"><span class="built_in">print</span>(result4)</span><br></pre></td></tr></table></figure><ol start="5"><li>获取第三个 li 标签的节点（两种方法）</li></ol><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">result = data.xpath(<span class="string">&#x27;//li[3]&#x27;</span>).extract()</span><br><span class="line">result = data.xpath(<span class="string">&#x27;//li&#x27;</span>)[<span class="number">2</span>].extract()</span><br><span class="line"><span class="built_in">print</span>(result)</span><br></pre></td></tr></table></figure><ol start="6"><li>通过定位属性的方法获取第四个 a 标签</li></ol><figure class="highlight python"><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">result = data.xpath(<span class="string">&#x27;//a[@href=&quot;link4.html&quot;]&#x27;</span>).extract()</span><br><span class="line"><span class="built_in">print</span>(result)</span><br></pre></td></tr></table></figure><ol start="7"><li>用属性定位标签，获取第四个 a 标签包裹的文本内容</li></ol><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">result = data.xpath(<span class="string">&#x27;//a[@href=&quot;link4.html&quot;]/text()&#x27;</span>).extract()</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(result)</span><br></pre></td></tr></table></figure><ol start="8"><li>获取第五个 a 标签的href属性值</li></ol><figure class="highlight python"><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">result = data.xpath(<span class="string">&#x27;//li[5]/a/@href&#x27;</span>).extract()</span><br><span class="line"><span class="built_in">print</span>(result)</span><br></pre></td></tr></table></figure><p><strong>可以将上面的代码复制到本地 print一下</strong></p><hr><p>或者直接使用谷歌浏览器插件 xpath helper </p><hr><p><strong>下载方式：</strong></p><ol><li><p>谷歌商店下载–&gt; <a href="https://chrome.google.com/webstore/detail/xpath-helper/hgimnogjllphhhkhlmebbmlgjoejdpjl?utm_source=chrome-ntp-icon">下载地址</a></p></li><li><p>本地下载–&gt; <a href="../../img/xpath.crx">下载地址</a></p></li></ol><blockquote><p>本地下载安装方法可以百度，很简单的–&gt;<a href="https://www.baidu.com/s?ie=UTF-8&wd=%E8%B0%B7%E6%AD%8C%E6%B5%8F%E8%A7%88%E5%99%A8%E6%8F%92%E4%BB%B6%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B">传送门</a></p></blockquote>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;介绍&quot;&gt;&lt;a href=&quot;#介绍&quot; class=&quot;headerlink&quot; title=&quot;介绍&quot;&gt;&lt;/a&gt;介绍&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;XPath&lt;/strong&gt; (XML Path Language) 是一门在 HTML&#92;XML 文档中查找信息的&lt;strong&gt;语言&lt;/strong&gt;，可用来在 HTML&#92;XML 文档中对&lt;strong&gt;元素和属性进行遍历&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    <category term="Python教程" scheme="https://blog.bugjava.cn/categories/Python%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="xpath" scheme="https://blog.bugjava.cn/tags/xpath/"/>
    
    <category term="python" scheme="https://blog.bugjava.cn/tags/python/"/>
    
  </entry>
  
  <entry>
    <title>爬取免费代理IP</title>
    <link href="https://blog.bugjava.cn/post/dailiip/"/>
    <id>https://blog.bugjava.cn/post/dailiip/</id>
    <published>2020-04-19T06:23:35.000Z</published>
    <updated>2023-04-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h1><blockquote><p>每次爬网站的时候总是被一些网站的反爬机制给封IP，所以就需要一些代理IP，但是很多代理IP都要钱，不要钱的很多不能用，所以就写了这么个代码来爬取代理IP</p></blockquote><span id="more"></span><h1 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h1><ol><li>确定爬取的url路径，headers参数</li><li>发送请求 – requests 模拟浏览器发送请求，获取响应数据</li><li>解析数据 – parsel  转化为Selector对象，Selector对象具有xpath的方法，能够对转化的数据进行处理</li><li>保存数据</li></ol><h1 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h1><ul><li>PYthon3.7</li><li>pycharm （其他的编辑器也可以）</li><li>模块 requests parsel time(安装模块指令<code>pip install requests &amp;&amp; pip install parsel</code>)</li></ul><h1 id="目标网站"><a href="#目标网站" class="headerlink" title="目标网站"></a>目标网站</h1><p><a href="https://www.kuaidaili.com/free">https://www.kuaidaili.com/free</a></p><h1 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h1><h2 id="第一步"><a href="#第一步" class="headerlink" title="第一步"></a>第一步</h2><p>导入模块，确定爬取的url路径，headers参数</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> parsel</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"></span><br><span class="line">base_url = <span class="string">&#x27;https://www.kuaidaili.com/free/inha/1/&#x27;</span></span><br><span class="line">headers = &#123;</span><br><span class="line"><span class="string">&#x27;User-Agent&#x27;</span>: <span class="string">&#x27;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36&#x27;</span>&#125;</span><br></pre></td></tr></table></figure><h2 id="第二步"><a href="#第二步" class="headerlink" title="第二步"></a>第二步</h2><p>发送请求 – requests 模拟浏览器发送请求，获取响应数据</p><figure class="highlight python"><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">response = requests.get(base_url, headers=headers)</span><br><span class="line">data = response.text</span><br></pre></td></tr></table></figure><h2 id="第三步"><a href="#第三步" class="headerlink" title="第三步"></a>第三步</h2><p>解析数据 – parsel  转化为Selector对象，Selector对象具有xpath的方法，能够对转化的数据进行处理</p><figure class="highlight python"><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">html_data = parsel.Selector(data)</span><br><span class="line">parse_list = html_data.xpath(<span class="string">&#x27;//table[@class=&quot;table table-bordered table-striped&quot;]/tbody/tr&#x27;</span>)  <span class="comment"># 返回Selector对象</span></span><br></pre></td></tr></table></figure><h2 id="第四步"><a href="#第四步" class="headerlink" title="第四步"></a>第四步</h2><p>循环遍历，二次提取，构建代理ip字典</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> tr <span class="keyword">in</span> parse_list:</span><br><span class="line">proxies_dict = &#123;&#125;</span><br><span class="line">http_type = tr.xpath(<span class="string">&#x27;./td[4]/text()&#x27;</span>).extract_first()</span><br><span class="line">ip_num = tr.xpath(<span class="string">&#x27;./td[1]/text()&#x27;</span>).extract_first()</span><br><span class="line">port_num = tr.xpath(<span class="string">&#x27;./td[2]/text()&#x27;</span>).extract_first()</span><br><span class="line">proxies_dict[http_type] = ip_num + <span class="string">&#x27;:&#x27;</span> + port_num</span><br><span class="line"><span class="built_in">print</span>(proxies_dict)</span><br><span class="line">proxies_list.append(proxies_dict)</span><br><span class="line">time.sleep(<span class="number">0.5</span>)</span><br><span class="line"><span class="built_in">print</span>(proxies_list)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;获取到的代理ip数量：&quot;</span>, <span class="built_in">len</span>(proxies_list), <span class="string">&#x27;个&#x27;</span>)</span><br></pre></td></tr></table></figure><h2 id="第五步"><a href="#第五步" class="headerlink" title="第五步"></a>第五步</h2><p>检测代理ip可用性，用获取到的IP访问百度或者其他网站，就可以检测其可用性</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">check_ip</span>(<span class="params">proxies_list</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;检测ip的方法&quot;&quot;&quot;</span></span><br><span class="line">    headers = &#123;</span><br><span class="line">        <span class="string">&#x27;User-Agent&#x27;</span>: <span class="string">&#x27;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36&#x27;</span>&#125;</span><br><span class="line"> </span><br><span class="line">    can_use = []</span><br><span class="line">    <span class="keyword">for</span> proxy <span class="keyword">in</span> proxies_list:</span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            response = requests.get(<span class="string">&#x27;http://www.baidu.com&#x27;</span>, headers=headers, proxies=proxy, timeout=<span class="number">0.1</span>)  <span class="comment"># 超时报错</span></span><br><span class="line">            <span class="keyword">if</span> response.status_code == <span class="number">200</span>:</span><br><span class="line">                can_use.append(proxy)</span><br><span class="line">        <span class="keyword">except</span> Exception <span class="keyword">as</span> error:</span><br><span class="line">            <span class="built_in">print</span>(error)</span><br><span class="line">        <span class="keyword">finally</span>:</span><br><span class="line">            <span class="built_in">print</span>(<span class="string">&quot;当前ip：&quot;</span>, proxy, <span class="string">&#x27;检测完成&#x27;</span>)</span><br><span class="line"> </span><br><span class="line">    <span class="keyword">return</span> can_use</span><br></pre></td></tr></table></figure><p>打印出数据</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></pre></td><td class="code"><pre><span class="line">can_use = check_ip(proxies_list)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;能用的代理：&quot;</span>, can_use)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;能用的代理数量：&quot;</span>, <span class="built_in">len</span>(can_use))</span><br></pre></td></tr></table></figure><hr><h1 id="完整代码"><a href="#完整代码" class="headerlink" title="完整代码"></a>完整代码</h1><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> parsel</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="keyword">def</span> <span class="title function_">check_ip</span>(<span class="params">proxies_list</span>):</span><br><span class="line">    headers = &#123;</span><br><span class="line">        <span class="string">&#x27;User-Agent&#x27;</span>: <span class="string">&#x27;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36&#x27;</span>&#125;</span><br><span class="line"> </span><br><span class="line">    can_use = []</span><br><span class="line">    <span class="keyword">for</span> proxy <span class="keyword">in</span> proxies_list:</span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            response = requests.get(<span class="string">&#x27;http://www.baidu.com&#x27;</span>, headers=headers, proxies=proxy, timeout=<span class="number">0.1</span>)  <span class="comment"># 超时报错</span></span><br><span class="line">            <span class="keyword">if</span> response.status_code == <span class="number">200</span>:</span><br><span class="line">                can_use.append(proxy)</span><br><span class="line">        <span class="keyword">except</span> Exception <span class="keyword">as</span> error:</span><br><span class="line">            <span class="built_in">print</span>(error)</span><br><span class="line">        <span class="keyword">finally</span>:</span><br><span class="line">            <span class="built_in">print</span>(<span class="string">&quot;当前ip：&quot;</span>, proxy, <span class="string">&#x27;检测完成&#x27;</span>)</span><br><span class="line"> </span><br><span class="line">    <span class="keyword">return</span> can_use</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">proxies_list = []</span><br><span class="line"><span class="keyword">for</span> page <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="number">10</span>): <span class="comment">#更换数字，选择爬取页数</span></span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&#x27;++++++++++++++++++++++++++++正在爬取第&#123;&#125;页数据+++++++++++++++++++++++++++++&#x27;</span>.<span class="built_in">format</span>(page))</span><br><span class="line">    base_url = <span class="string">&#x27;https://www.kuaidaili.com/free/inha/&#123;&#125;/&#x27;</span>.<span class="built_in">format</span>(page)</span><br><span class="line">    headers = &#123;</span><br><span class="line">        <span class="string">&#x27;User-Agent&#x27;</span>: <span class="string">&#x27;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36&#x27;</span>&#125;</span><br><span class="line"></span><br><span class="line">    response = requests.get(base_url, headers=headers)</span><br><span class="line">    data = response.text</span><br><span class="line">    html_data = parsel.Selector(data)</span><br><span class="line">    parse_list = html_data.xpath(<span class="string">&#x27;//table[@class=&quot;table table-bordered table-striped&quot;]/tbody/tr&#x27;</span>)  <span class="comment"># 返回Selector对象</span></span><br><span class="line">    <span class="keyword">for</span> tr <span class="keyword">in</span> parse_list:</span><br><span class="line">        proxies_dict = &#123;&#125;</span><br><span class="line">        http_type = tr.xpath(<span class="string">&#x27;./td[4]/text()&#x27;</span>).extract_first()</span><br><span class="line">        ip_num = tr.xpath(<span class="string">&#x27;./td[1]/text()&#x27;</span>).extract_first()</span><br><span class="line">        port_num = tr.xpath(<span class="string">&#x27;./td[2]/text()&#x27;</span>).extract_first()</span><br><span class="line">        proxies_dict[http_type] = ip_num + <span class="string">&#x27;:&#x27;</span> + port_num</span><br><span class="line">        <span class="built_in">print</span>(proxies_dict)</span><br><span class="line">        proxies_list.append(proxies_dict)</span><br><span class="line">        time.sleep(<span class="number">0.5</span>)</span><br><span class="line"> </span><br><span class="line"><span class="built_in">print</span>(proxies_list)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;获取到的代理ip数量：&quot;</span>, <span class="built_in">len</span>(proxies_list), <span class="string">&#x27;个&#x27;</span>)</span><br><span class="line">can_use = check_ip(proxies_list)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;能用的代理：&quot;</span>, can_use)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;能用的代理数量：&quot;</span>, <span class="built_in">len</span>(can_use))</span><br></pre></td></tr></table></figure><hr><blockquote class="blockquote-center" >使用代理访问的食用方法</blockquote><p><strong>就拿我们经常使用的 requests 库来说</strong></p><p>使用代理 ip 方法如下</p><ol><li>定义代理IP</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">proxies = &#123; </span><br><span class="line">        <span class="string">&#x27;http&#x27;</span> : <span class="string">&#x27;http://xx.xxx.xxx.xxx:xxxx&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;http&#x27;</span> : <span class="string">&#x27;http://xxx.xx.xx.xxx:xxx&#x27;</span>,</span><br><span class="line">        ....</span><br><span class="line">    &#125;  </span><br></pre></td></tr></table></figure><ol start="2"><li>使用代理</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">response = requests.get(url,proxies=proxies)</span><br></pre></td></tr></table></figure><p>和请求头放一起</p><hr><p>接下来就可以创建一个属于自己的IP池了</p>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;介绍&quot;&gt;&lt;a href=&quot;#介绍&quot; class=&quot;headerlink&quot; title=&quot;介绍&quot;&gt;&lt;/a&gt;介绍&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;每次爬网站的时候总是被一些网站的反爬机制给封IP，所以就需要一些代理IP，但是很多代理IP都要钱，不要钱的很多不能用，所以就写了这么个代码来爬取代理IP&lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    <category term="Python案例" scheme="https://blog.bugjava.cn/categories/Python%E6%A1%88%E4%BE%8B/"/>
    
    
    <category term="python" scheme="https://blog.bugjava.cn/tags/python/"/>
    
    <category term="爬虫" scheme="https://blog.bugjava.cn/tags/%E7%88%AC%E8%99%AB/"/>
    
    <category term="代理IP" scheme="https://blog.bugjava.cn/tags/%E4%BB%A3%E7%90%86IP/"/>
    
  </entry>
  
  <entry>
    <title>爬取某网站小姐姐壁纸</title>
    <link href="https://blog.bugjava.cn/post/xiaojiejiebizhi/"/>
    <id>https://blog.bugjava.cn/post/xiaojiejiebizhi/</id>
    <published>2020-04-05T12:53:00.000Z</published>
    <updated>2023-04-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<span id="more"></span><h1 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h1><blockquote><p>美桌壁纸小姐姐壁纸爬取</p></blockquote><h1 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h1><ul><li>PYthon3.8（我用的是这个版本的）</li><li>pycharm （其他的编辑器也可以）</li><li>模块：requests，parsel，os</li></ul><h1 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h1><p>爬虫的思路</p><ol><li>分析目标网页，确定爬取的url路径，headers参数</li><li>发送请求 – requests 模拟浏览器发送请求，获取响应数据</li><li>解析数据 – parsel  转化为Selector对象，Selector对象具有xpath的方法，能够对转化的数据进行处理</li><li>保存数据</li></ol><h1 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h1><h2 id="第一步"><a href="#第一步" class="headerlink" title="第一步"></a>第一步</h2><p>确定爬取的url路径，headers参数</p><figure class="highlight python"><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">base_url = <span class="string">&#x27;http://www.win4000.com/mobile_2340_0_0_1.html&#x27;</span></span><br><span class="line">headers = &#123;<span class="string">&#x27;User-Agent&#x27;</span>: <span class="string">&#x27;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36&#x27;</span>&#125;</span><br></pre></td></tr></table></figure><p>User-Agent在浏览器的F12 Network里面获取（里面找到headers，在最下面就有你自己浏览器的User-Agent参数）</p><h2 id="第二步"><a href="#第二步" class="headerlink" title="第二步"></a>第二步</h2><p>发送请求 – requests 模拟浏览器发送请求，获取响应数据</p><figure class="highlight python"><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">response = requests.get(base_url, headers=headers)</span><br><span class="line">data = response.text</span><br></pre></td></tr></table></figure><h2 id="第三步"><a href="#第三步" class="headerlink" title="第三步"></a>第三步</h2><p>解析数据 – parsel  转化为Selector对象，Selector对象具有xpath的方法，能够对转化的数据进行处理</p><figure class="highlight python"><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">html_data = parsel.Selector(data)</span><br><span class="line">data_list = html_data.xpath(<span class="string">&#x27;//div[@class=&quot;Left_bar&quot;]//ul/li/a/@href|//div[@class=&quot;Left_bar&quot;]//ul/li/a/@title&#x27;</span>).extract()</span><br></pre></td></tr></table></figure><p>使用列表推导式对列表进行分组</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">data_list = [data_list[i:i + <span class="number">2</span>] <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, <span class="built_in">len</span>(data_list), <span class="number">2</span>)]</span><br></pre></td></tr></table></figure><p>创建图片的文件夹</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> <span class="keyword">not</span> os.path.exists(<span class="string">&#x27;img\\&#x27;</span> + file_name):</span><br><span class="line">    os.mkdir(<span class="string">&#x27;img\\&#x27;</span> + file_name)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&#x27;正在下载：&#x27;</span>, file_name)</span><br></pre></td></tr></table></figure><p>发送详情页的请求,解析出总页数</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></pre></td><td class="code"><pre><span class="line">response_2 = requests.get(html_url, headers=headers).text</span><br><span class="line">html_2 = parsel.Selector(response_2)</span><br><span class="line">page_num = html_2.xpath(<span class="string">&#x27;//div[@class=&quot;ptitle&quot;]//em/text()&#x27;</span>).extract_first()</span><br></pre></td></tr></table></figure><h2 id="最后"><a href="#最后" class="headerlink" title="最后"></a>最后</h2><p>构建相册翻页的url地址，解析每一页的图片url地址，保存数据</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> url <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="built_in">int</span>(page_num) + <span class="number">1</span>):</span><br><span class="line">url_list = html_url.split(<span class="string">&#x27;.&#x27;</span>)</span><br><span class="line">all_url = url_list[<span class="number">0</span>] + <span class="string">&#x27;.&#x27;</span> + url_list[<span class="number">1</span>] + <span class="string">&#x27;.&#x27;</span> + url_list[<span class="number">2</span>] + <span class="string">&#x27;_&#x27;</span> + <span class="built_in">str</span>(url) + <span class="string">&#x27;.&#x27;</span> + url_list[<span class="number">3</span>]</span><br><span class="line">response_3 = requests.get(all_url, headers=headers).text</span><br><span class="line">html_3 = parsel.Selector(response_3)</span><br><span class="line">img_url = html_3.xpath(<span class="string">&#x27;//div[@class=&quot;pic-meinv&quot;]//img/@src&#x27;</span>).extract_first()</span><br><span class="line">img_data = requests.get(img_url, headers=headers).content</span><br><span class="line"><span class="comment"># 图片的文件名</span></span><br><span class="line">img_name = <span class="built_in">str</span>(url) + <span class="string">&#x27;.jpg&#x27;</span></span><br><span class="line"><span class="comment"># 保存数据</span></span><br><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&#x27;img\\&#123;&#125;\\&#x27;</span>.<span class="built_in">format</span>(file_name) + img_name, <span class="string">&#x27;wb&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&#x27;下载完成：&#x27;</span>, img_name)</span><br><span class="line">f.write(img_data)</span><br></pre></td></tr></table></figure><h1 id="完整代码"><a href="#完整代码" class="headerlink" title="完整代码"></a>完整代码</h1><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> parsel</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line">base_url = <span class="string">&#x27;http://www.win4000.com/mobile_2340_0_0_1.html&#x27;</span></span><br><span class="line">headers = &#123;<span class="string">&#x27;User-Agent&#x27;</span>: <span class="string">&#x27;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36&#x27;</span>&#125;</span><br><span class="line">response = requests.get(base_url, headers=headers)</span><br><span class="line">data = response.text</span><br><span class="line">html_data = parsel.Selector(data)</span><br><span class="line">data_list = html_data.xpath(<span class="string">&#x27;//div[@class=&quot;Left_bar&quot;]//ul/li/a/@href|//div[@class=&quot;Left_bar&quot;]//ul/li/a/@title&#x27;</span>).extract()</span><br><span class="line">data_list = [data_list[i:i + <span class="number">2</span>] <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>, <span class="built_in">len</span>(data_list), <span class="number">2</span>)]</span><br><span class="line"><span class="keyword">for</span> alist <span class="keyword">in</span> data_list:</span><br><span class="line">    html_url = alist[<span class="number">0</span>]</span><br><span class="line">    file_name = alist[<span class="number">1</span>]</span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> os.path.exists(<span class="string">&#x27;img\\&#x27;</span> + file_name):</span><br><span class="line">        os.mkdir(<span class="string">&#x27;img\\&#x27;</span> + file_name)</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&#x27;正在下载：&#x27;</span>, file_name)</span><br><span class="line">    response_2 = requests.get(html_url, headers=headers).text</span><br><span class="line">    html_2 = parsel.Selector(response_2)</span><br><span class="line">    page_num = html_2.xpath(<span class="string">&#x27;//div[@class=&quot;ptitle&quot;]//em/text()&#x27;</span>).extract_first()</span><br><span class="line">    <span class="keyword">for</span> url <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="built_in">int</span>(page_num) + <span class="number">1</span>):</span><br><span class="line">        url_list = html_url.split(<span class="string">&#x27;.&#x27;</span>)</span><br><span class="line">        all_url = url_list[<span class="number">0</span>] + <span class="string">&#x27;.&#x27;</span> + url_list[<span class="number">1</span>] + <span class="string">&#x27;.&#x27;</span> + url_list[<span class="number">2</span>] + <span class="string">&#x27;_&#x27;</span> + <span class="built_in">str</span>(url) + <span class="string">&#x27;.&#x27;</span> + url_list[<span class="number">3</span>]</span><br><span class="line">        response_3 = requests.get(all_url, headers=headers).text</span><br><span class="line">        html_3 = parsel.Selector(response_3)</span><br><span class="line">        img_url = html_3.xpath(<span class="string">&#x27;//div[@class=&quot;pic-meinv&quot;]//img/@src&#x27;</span>).extract_first()</span><br><span class="line">        img_data = requests.get(img_url, headers=headers).content</span><br><span class="line">        img_name = <span class="built_in">str</span>(url) + <span class="string">&#x27;.jpg&#x27;</span></span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&#x27;img\\&#123;&#125;\\&#x27;</span>.<span class="built_in">format</span>(file_name) + img_name, <span class="string">&#x27;wb&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">            <span class="built_in">print</span>(<span class="string">&#x27;下载完成：&#x27;</span>, img_name)</span><br><span class="line">            f.write(img_data)</span><br></pre></td></tr></table></figure><hr><p>说明：这个代码并不能爬取全站图片，详细的自己研究</p><hr><p><strong><a href="https://www.lanzous.com/b0d7yfn6j">转送门</a></strong><br>好像不是特别全上传的时候似乎漏掉了几个</p><hr><p>偶然发现pyinstaller这个模块，这个模块可以把py程序封装成exe程序，在没有py环境的电脑上也可以运行<br>想要的可以直接下载，exe软件下载地址–&gt;<strong><a href="https://www.lanzous.com/b0d7ykpvg">传送门</a></strong></p><p><img src="https://cdn.seovx.com/?mom=302" alt="预览"></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;img src=&quot;https://cdn.seovx.com/?mom=302&quot; alt=&quot;封面&quot;&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="Python案例" scheme="https://blog.bugjava.cn/categories/Python%E6%A1%88%E4%BE%8B/"/>
    
    
    <category term="python" scheme="https://blog.bugjava.cn/tags/python/"/>
    
    <category term="爬虫" scheme="https://blog.bugjava.cn/tags/%E7%88%AC%E8%99%AB/"/>
    
    <category term="图片" scheme="https://blog.bugjava.cn/tags/%E5%9B%BE%E7%89%87/"/>
    
    <category term="壁纸" scheme="https://blog.bugjava.cn/tags/%E5%A3%81%E7%BA%B8/"/>
    
  </entry>
  
  <entry>
    <title>制作随机图片/视频api（本地/外链）</title>
    <link href="https://blog.bugjava.cn/post/imgvideoapi/"/>
    <id>https://blog.bugjava.cn/post/imgvideoapi/</id>
    <published>2020-04-01T02:51:01.000Z</published>
    <updated>2023-04-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="本地图片API"><a href="#本地图片API" class="headerlink" title="本地图片API"></a>本地图片API</h1><p>制作方法</p><p>新建一个PHP文件（名字可以自己取），在创建一个img文件夹，把图片放进去</p><p>把php文件和img文件夹上传到服务器然后访问域名&#x2F;PHP文件名就可以啦</p><p>php代码如下：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$img_array</span> = <span class="title function_ invoke__">glob</span>(<span class="string">&quot;img/*.&#123;gif,jpg,png&#125;&quot;</span>,GLOB_BRACE); </span><br><span class="line"><span class="variable">$img</span> = <span class="title function_ invoke__">array_rand</span>(<span class="variable">$img_array</span>); </span><br><span class="line"><span class="variable">$dz</span> = <span class="variable">$img_array</span>[<span class="variable">$img</span>];</span><br><span class="line"><span class="title function_ invoke__">header</span>(<span class="string">&quot;Location:&quot;</span>.<span class="variable">$dz</span>);</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><h1 id="外链图片API"><a href="#外链图片API" class="headerlink" title="外链图片API"></a>外链图片API</h1><p>制作方法</p><p>新建一个PHP文件（名字可以自己取）， images.txt文档文件，把外链图片地址放进去</p><p>把php文件和txt文档上传到服务器里就可以啦</p><p>PHP代码如下：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$arr</span>=<span class="title function_ invoke__">file</span>(<span class="string">&#x27;images.txt&#x27;</span>);</span><br><span class="line"><span class="variable">$n</span>=<span class="title function_ invoke__">count</span>(<span class="variable">$arr</span>)-<span class="number">1</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="variable">$i</span>=<span class="number">1</span>;<span class="variable">$i</span>&lt;=<span class="number">1</span>;<span class="variable">$i</span>++)&#123;</span><br><span class="line"><span class="variable">$x</span>=<span class="title function_ invoke__">rand</span>(<span class="number">0</span>,<span class="variable">$n</span>);</span><br><span class="line"><span class="title function_ invoke__">header</span>(<span class="string">&quot;Location:&quot;</span>.<span class="variable">$arr</span>[<span class="variable">$x</span>],<span class="string">&quot;\n&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><h1 id="本地视频API"><a href="#本地视频API" class="headerlink" title="本地视频API"></a>本地视频API</h1><p>创建一个video的文件夹，视频放进去，和本地图片API差不多</p><p>php代码如下：</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="variable">$video_array</span> = <span class="title function_ invoke__">glob</span>(<span class="string">&quot;video/*.&#123;mp4&#125;&quot;</span>,GLOB_BRACE); </span><br><span class="line"><span class="variable">$video</span> = <span class="title function_ invoke__">array_rand</span>(<span class="variable">$video_array</span>); </span><br><span class="line"><span class="variable">$dz</span> = <span class="variable">$video_array</span>[<span class="variable">$video</span>];</span><br><span class="line"><span class="title function_ invoke__">header</span>(<span class="string">&quot;Location:&quot;</span>.<span class="variable">$dz</span>);</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;本地图片API&quot;&gt;&lt;a href=&quot;#本地图片API&quot; class=&quot;headerlink&quot; title=&quot;本地图片API&quot;&gt;&lt;/a&gt;本地图片API&lt;/h1&gt;&lt;p&gt;制作方法&lt;/p&gt;
&lt;p&gt;新建一个PHP文件（名字可以自己取），在创建一个img文件夹，把图片放进去&lt;</summary>
      
    
    
    
    <category term="经验教程" scheme="https://blog.bugjava.cn/categories/%E7%BB%8F%E9%AA%8C%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="随机图片" scheme="https://blog.bugjava.cn/tags/%E9%9A%8F%E6%9C%BA%E5%9B%BE%E7%89%87/"/>
    
    <category term="API" scheme="https://blog.bugjava.cn/tags/API/"/>
    
    <category term="代码" scheme="https://blog.bugjava.cn/tags/%E4%BB%A3%E7%A0%81/"/>
    
    <category term="PHP" scheme="https://blog.bugjava.cn/tags/PHP/"/>
    
  </entry>
  
  <entry>
    <title>用Python爬取王者荣耀英雄皮肤海报图</title>
    <link href="https://blog.bugjava.cn/post/wzryphoto/"/>
    <id>https://blog.bugjava.cn/post/wzryphoto/</id>
    <published>2020-03-30T12:58:23.000Z</published>
    <updated>2023-04-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h1><blockquote><p>在某平台公开课上学了怎么用python爬取王者的全英雄皮肤海报图，然后自己敲了一遍，发现还不错，把图片全部都爬取下来了，本来想用来做壁纸，但是一看，实在太丑，然后。。然后就不知道这些图片能干啥了。现在就来分享一些爬取王者海报图的思路。</p></blockquote><span id="more"></span><h1 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h1><p>1，确定爬取的url路径</p><p>2，发送请求，一般需要模拟浏览器发送，需要用到 requests</p><p>3，解析数据，需要用json模块，json模块可以把json字符串转换换成Python可交互的数据</p><p>4，保存数据</p><h1 id="开始"><a href="#开始" class="headerlink" title="开始"></a>开始</h1><h2 id="第一步"><a href="#第一步" class="headerlink" title="第一步"></a>第一步</h2><p>确定爬取的url路径</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">#在王者官网打开检查</span><br><span class="line">base_url = &#x27;https://pvp.qq.com/web201605/js/herolist.json&#x27;</span><br></pre></td></tr></table></figure><h2 id="第二步"><a href="#第二步" class="headerlink" title="第二步"></a>第二步</h2><p>模拟浏览器发送请求 这里要用到requests 获取响应数据</p><figure class="highlight python"><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">response = requests.get(base_url)</span><br><span class="line">data_str = response.text  <span class="comment">#--字符串</span></span><br></pre></td></tr></table></figure><h2 id="第三步"><a href="#第三步" class="headerlink" title="第三步"></a>第三步</h2><p>解析数据，要用到json模块，json模块可以把 json字符串转化成python可交互的数据类型,</p><p>1，转换数据类型</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">data_list = json.loads(data_str) </span><br></pre></td></tr></table></figure><p>2,解析数据</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> data <span class="keyword">in</span> data_list:</span><br><span class="line">    <span class="comment"># 提取图片所需参数</span></span><br><span class="line">    ename = data[<span class="string">&#x27;ename&#x27;</span>]  <span class="comment"># 英雄编号</span></span><br><span class="line">    cname = data[<span class="string">&#x27;cname&#x27;</span>]  <span class="comment"># 英雄名字</span></span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        skin_name = data[<span class="string">&#x27;skin_name&#x27;</span>].split(<span class="string">&#x27;|&#x27;</span>)  <span class="comment"># 切割皮肤的名字，用于计算每个英雄有多少个皮肤</span></span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">        <span class="built_in">print</span>(e)</span><br><span class="line"> </span><br><span class="line">    <span class="comment"># http://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/524/524-bigskin-1.jpg</span></span><br><span class="line">    <span class="comment">#这是其中一个图片的url</span></span><br><span class="line">    <span class="comment"># http://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/ + 英雄编号 + &quot;/&quot; + 英雄编号-bigskin-皮肤序号 + &quot;.jpg&quot;</span></span><br><span class="line">    <span class="comment">#这是图片url的格式</span></span><br></pre></td></tr></table></figure><p>   3，构建皮肤数量循环（使用for循环）</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> skin_num <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="built_in">len</span>(skin_name) + <span class="number">1</span>):</span><br><span class="line">        skin_url = <span class="string">&#x27;http://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/&#x27;</span> + <span class="built_in">str</span>(ename) + <span class="string">&#x27;/&#x27;</span> + <span class="built_in">str</span>(</span><br><span class="line">            ename) + <span class="string">&#x27;-bigskin-&#x27;</span> + <span class="built_in">str</span>(skin_num) + <span class="string">&#x27;.jpg&#x27;</span></span><br></pre></td></tr></table></figure><p>4，请求图片数据</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">skin_data = requests.get(skin_url).content</span><br></pre></td></tr></table></figure><h2 id="第四步"><a href="#第四步" class="headerlink" title="第四步"></a>第四步</h2><p>保存数据</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&#x27;img\\&#x27;</span> + cname + <span class="string">&quot;-&quot;</span> + skin_name[skin_num - <span class="number">1</span>] + <span class="string">&#x27;.jpg&#x27;</span>, <span class="string">&#x27;wb&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">            <span class="built_in">print</span>(<span class="string">&#x27;正在下载皮肤：&#x27;</span>, cname + <span class="string">&quot;-&quot;</span> + skin_name[skin_num - <span class="number">1</span>])</span><br><span class="line">            f.write(skin_data)</span><br></pre></td></tr></table></figure><p>到这里就差不多结束了</p><h1 id="完整代码"><a href="#完整代码" class="headerlink" title="完整代码"></a>完整代码</h1><p>下面是一个完整代码</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></pre></td><td class="code"><pre><span class="line">base_url = <span class="string">&#x27;https://pvp.qq.com/web201605/js/herolist.json&#x27;</span></span><br><span class="line">response = requests.get(base_url)</span><br><span class="line">data_str = response.text</span><br><span class="line">data_list = json.loads(data_str)</span><br><span class="line"><span class="keyword">for</span> data <span class="keyword">in</span> data_list:</span><br><span class="line">    ename = data[<span class="string">&#x27;ename&#x27;</span>]  <span class="comment"># 英雄编号</span></span><br><span class="line">    cname = data[<span class="string">&#x27;cname&#x27;</span>]  <span class="comment"># 英雄名字</span></span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        skin_name = data[<span class="string">&#x27;skin_name&#x27;</span>].split(<span class="string">&#x27;|&#x27;</span>)</span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">        <span class="built_in">print</span>(e)</span><br><span class="line">    <span class="keyword">for</span> skin_num <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>, <span class="built_in">len</span>(skin_name) + <span class="number">1</span>):</span><br><span class="line">        skin_url = <span class="string">&#x27;http://game.gtimg.cn/images/yxzj/img201606/skin/hero-info/&#x27;</span> + <span class="built_in">str</span>(ename) + <span class="string">&#x27;/&#x27;</span> + <span class="built_in">str</span>(</span><br><span class="line">            ename) + <span class="string">&#x27;-bigskin-&#x27;</span> + <span class="built_in">str</span>(skin_num) + <span class="string">&#x27;.jpg&#x27;</span></span><br><span class="line">        skin_data = requests.get(skin_url).content</span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&#x27;img\\&#x27;</span> + cname + <span class="string">&quot;-&quot;</span> + skin_name[skin_num - <span class="number">1</span>] + <span class="string">&#x27;.jpg&#x27;</span>, <span class="string">&#x27;wb&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">            <span class="built_in">print</span>(<span class="string">&#x27;正在下载皮肤：&#x27;</span>, cname + <span class="string">&quot;-&quot;</span> + skin_name[skin_num - <span class="number">1</span>])</span><br><span class="line">            f.write(skin_data) </span><br></pre></td></tr></table></figure><p><strong>注意</strong>：要在目录下新建一个img的文件夹</p><hr><p><a href="https://www.lanzous.com/iat8oub">转送门</a></p>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;介绍&quot;&gt;&lt;a href=&quot;#介绍&quot; class=&quot;headerlink&quot; title=&quot;介绍&quot;&gt;&lt;/a&gt;介绍&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;在某平台公开课上学了怎么用python爬取王者的全英雄皮肤海报图，然后自己敲了一遍，发现还不错，把图片全部都爬取下来了，本来想用来做壁纸，但是一看，实在太丑，然后。。然后就不知道这些图片能干啥了。现在就来分享一些爬取王者海报图的思路。&lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    <category term="Python案例" scheme="https://blog.bugjava.cn/categories/Python%E6%A1%88%E4%BE%8B/"/>
    
    
    <category term="python" scheme="https://blog.bugjava.cn/tags/python/"/>
    
    <category term="爬虫" scheme="https://blog.bugjava.cn/tags/%E7%88%AC%E8%99%AB/"/>
    
    <category term="王者荣耀" scheme="https://blog.bugjava.cn/tags/%E7%8E%8B%E8%80%85%E8%8D%A3%E8%80%80/"/>
    
    <category term="图片" scheme="https://blog.bugjava.cn/tags/%E5%9B%BE%E7%89%87/"/>
    
  </entry>
  
  <entry>
    <title>利用NodeJs本地部署UnblockNeteaseMusic</title>
    <link href="https://blog.bugjava.cn/post/PCUnblockNeteaseMusic/"/>
    <id>https://blog.bugjava.cn/post/PCUnblockNeteaseMusic/</id>
    <published>2020-03-30T01:54:55.000Z</published>
    <updated>2023-04-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h1><blockquote><p>考虑到没有服务器，我在网上看见了Windows的一键启动方法，那么本文给大家带来一个一键启动的方法以及设置开启自启的方法。</p></blockquote><span id="more"></span><div class="tabs" id="link"><ul class="nav-tabs"><button type="button" class="tab  active" data-href="link-1">手动部署</button><button type="button" class="tab " data-href="link-2">服务部署（推荐）</button></ul><div class="tab-contents"><div class="tab-item-content active" id="link-1"><h1 id="部署安装"><a href="#部署安装" class="headerlink" title="部署安装"></a>部署安装</h1><h2 id="第一步"><a href="#第一步" class="headerlink" title="第一步"></a>第一步</h2><p>  安装NodeJS环境 下载地址：<a href="http://nodejs.cn/download/">http://nodejs.cn/download/</a> 根据你的系统选择合适的下载</p><p><strong>备注</strong>：已经安装过的可以跳过这一步。如何查看自己是否安装过？使用Win+R键打开CMD，输入node -v即可，如有返回结果是NodeJs版本号即代表已安装</p><h2 id="第二步"><a href="#第二步" class="headerlink" title="第二步"></a>第二步</h2><p><strong>下载项目文件</strong>（解压到自己想保存的位置）</p><p>下载地址：<a href="https://github.com/UnblockNeteaseMusic/server/archive/refs/heads/enhanced.zip">https://github.com/UnblockNeteaseMusic/server/archive/refs/heads/enhanced.zip</a></p><h2 id="第三步"><a href="#第三步" class="headerlink" title="第三步"></a>第三步</h2><p><strong>记录本地IP地址</strong></p><p>使用Win+R键都打开CMD，输入ping music.163.com。并记录Ping出来的IP</p><h2 id="第四步"><a href="#第四步" class="headerlink" title="第四步"></a>第四步</h2><p><strong>制作一键启动bat脚本</strong></p><p>新建一个文本文档，把以下三条代码复制进去另存为 music.bat （复制进去后记得修改哦~）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">代码中 端口自定义，IP修改为刚刚记录的IP</span><br><span class="line">@echo off   cd 项目文件解压位置</span><br><span class="line">node app.js -p 准备放行的端口 -f 刚刚Ping出来的IP</span><br></pre></td></tr></table></figure><blockquote><p>位置信息:右键下载的文件夹，选择属性<br>端口是自己设置的（我选择的是8080端口）<br>做好的bat脚本放到下载的文件里</p></blockquote><h2 id="第五步"><a href="#第五步" class="headerlink" title="第五步"></a>第五步</h2><p>右击bat文件，点击创建快捷方式，并把快捷方式放到桌面等显眼位置。以后启动即可打开快捷方式即可。</p><p><strong>备注</strong>：如需开机自启请看第六步，无需请直接看第七步<br>打开bat文件如果显示</p><p><strong><code>HTTP Server running @ http://0.0.0.0:8080</code></strong></p><p>就表示成功</p><h2 id="第六步"><a href="#第六步" class="headerlink" title="第六步"></a>第六步</h2><p><strong>设置开机自启</strong></p><p>新建一个文本文档，把以下三条代码复制进去另存为 music.vbs</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">记得修改路径哦，不要无脑复制粘贴</span><br><span class="line">Set ws = CreateObject(&quot;Wscript.Shell&quot;)</span><br><span class="line">ws.run &quot;cmd /c music.bat&quot;,vbhide</span><br></pre></td></tr></table></figure><p>将 VBS 脚本放置在项目文件夹中，并创建快捷方式</p><p>将 VBS 创建快捷方式放到自启文件夹（C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp）</p></div><div class="tab-item-content" id="link-2"><h2 id="第一步"><a href="#第一步" class="headerlink" title="第一步"></a>第一步</h2><p>  安装NodeJS环境 下载地址：<a href="http://nodejs.cn/download/">http://nodejs.cn/download/</a> 根据你的系统选择合适的下载</p><p><strong>备注</strong>：已经安装过的可以跳过这一步。如何查看自己是否安装过？使用Win+R键打开CMD，输入node -v即可，如有返回结果是NodeJs版本号即代表已安装</p><h2 id="第二步"><a href="#第二步" class="headerlink" title="第二步"></a>第二步</h2><p><strong>下载项目文件</strong>（解压到自己想保存的位置）</p><p>下载地址：<a href="https://github.com/UnblockNeteaseMusic/server/archive/refs/heads/enhanced.zip">https://github.com/UnblockNeteaseMusic/server/archive/refs/heads/enhanced.zip</a></p><h2 id="第三步"><a href="#第三步" class="headerlink" title="第三步"></a>第三步</h2><p>安装依赖，在解压的目录下面运行<code>npm i</code></p><p>安装成功后会在项目根目录下生成<code>node_module</code>文件夹</p><p>然后在项目根目录运行 node .&#x2F;nw.js。（最好以管理员权限运行）会有弹窗，直接确定即可。如果有安全管家等软件可能会阻止，直接允许即可。运行成功后可在电脑服务中看到该服务。</p><p>如果想要卸载已安装的服务，请再次运行 <code>node ./nw.js</code>。</p><p>安装服务后，会在项目根目录生成 <code>daemon</code> 文件夹。可在这里查看日志。</p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="anzhiyufont anzhiyu-icon-arrow-up"></i></button></div></div><p><strong>客户端设置</strong></p><p>右上角【⚙】 – 【工具】 – 【Http代理】 – 点击【自定义代理】 – 下拉框选择【HTTP代理】</p><p>分别输入 服务器 和 端口 点击怕【确定】即可，会提示要重启客户端，重启即可</p><p>（服务器输入本地IP（一般是127.0.0.1）端口输入你刚刚设置的，我用的是8080端口）</p><hr><p><strong>接下来就可以愉快的听歌了</strong>由于不方便放图所以就没有图片了，不懂的可以加我QQ。</p>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;介绍&quot;&gt;&lt;a href=&quot;#介绍&quot; class=&quot;headerlink&quot; title=&quot;介绍&quot;&gt;&lt;/a&gt;介绍&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;考虑到没有服务器，我在网上看见了Windows的一键启动方法，那么本文给大家带来一个一键启动的方法以及设置开启自启的方法。&lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    <category term="经验教程" scheme="https://blog.bugjava.cn/categories/%E7%BB%8F%E9%AA%8C%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="教程" scheme="https://blog.bugjava.cn/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="音乐" scheme="https://blog.bugjava.cn/tags/%E9%9F%B3%E4%B9%90/"/>
    
    <category term="github" scheme="https://blog.bugjava.cn/tags/github/"/>
    
  </entry>
  
  <entry>
    <title>使用宝塔安装UnblockNeteaseMusic</title>
    <link href="https://blog.bugjava.cn/post/UnblockNeteaseMusic/"/>
    <id>https://blog.bugjava.cn/post/UnblockNeteaseMusic/</id>
    <published>2020-03-29T08:47:28.000Z</published>
    <updated>2023-04-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h1><blockquote><p>UnblockNeteaseMusic是一款可以给你解除网易云音乐海外限制并解锁变灰(无版权)歌曲的工具，让你可以听取客户端任何的歌曲，而不受到限制，此前该类似工具挺多的，不过貌似都不维护或者失效了，这里提到的项目更新很频繁，支持Windows、MacOS、安卓、IOS等设备，所以就分享一下使用方法。</p></blockquote><span id="more"></span><h1 id="截图"><a href="#截图" class="headerlink" title="截图"></a>截图</h1><p><img src="/images/UnblockNeteaseMusic(1).png" alt="使用前"><br><img src="/images/UnblockNeteaseMusic(2).png" alt="使用后"></p><h1 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h1><ul><li>使用网易云旧链&#x2F;QQ&#x2F;虾米&#x2F;百度&#x2F;酷狗&#x2F;酷我&#x2F;咕咪&#x2F;JOOX音源替换变灰歌曲链接(默认仅启用前四)。</li><li>为请求增加X-Real-IP参数解锁海外限制，支持指定网易云服务器IP，支持设置上游HTTP&#x2F;HTTPS代理。</li><li>完整的流量代理功能(HTTP&#x2F;HTTPS)，可直接作为系统代理(同时支持PAC)。</li></ul><h1 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h1><ul><li><strong>github地址</strong>:<a href="https://github.com/UnblockNeteaseMusic/server">https://github.com/UnblockNeteaseMusic/server</a></li></ul><h2 id="部署环境"><a href="#部署环境" class="headerlink" title="部署环境"></a>部署环境</h2><ul><li><p>推荐5M带宽以上的服务器、VPS都可以（只要能安装宝塔面板）</p></li><li><p>测试服务器：某轻量服务器</p></li><li><p>测试系统：CentOS 7.1</p></li></ul><h2 id="部署方法"><a href="#部署方法" class="headerlink" title="部署方法"></a>部署方法</h2><h3 id="第一步"><a href="#第一步" class="headerlink" title="第一步"></a>第一步</h3><p>  安装宝塔面板，跳过宝塔面板的推荐安装（用不到）、并且打开软件商店 -&gt; 运行环境 -&gt; 安装PM2管理器<br><img src="/images/music1.png" alt=" "></p><h3 id="第二步"><a href="#第二步" class="headerlink" title="第二步"></a>第二步</h3><p>  使用宝塔自带的SSH工具或使用Xshell工具连接服务器、并下载待部署项目<br><img src="/images/music2.png" alt=" "><br>  <strong>连接服务器后执行下面的命令行</strong></p><p><strong>代码</strong><code>git clone https://github.com/UnblockNeteaseMusic/server.git</code><br><img src="/images/music3.png" alt=" "></p><h3 id="第三步"><a href="#第三步" class="headerlink" title="第三步"></a>第三步</h3><p>  在&#x2F;root&#x2F;UnblockNeteaseMusic&#x2F;src&#x2F;app.js 中找到端口并记录下来（可以改为自己想要的端口）默认端口为8080，如果需要用其他端口，可以直接将8080换成你需要的端口<br><img src="/images/music4.png"></p><h3 id="第四步"><a href="#第四步" class="headerlink" title="第四步"></a>第四步</h3><p>在宝塔面板左侧安全中 将刚刚看见的端口放行<em><strong>名称随便填</strong></em>（如果你用了什么端口就放行什么端口）（项目默认8080端口）<br><strong>注意</strong>：部分服务器厂商（例如：阿里云、腾讯云、天翼云等等）会开启安全组，宝塔开放端口后还要去服务器控制面板放行对应端口</p><h3 id="第五步"><a href="#第五步" class="headerlink" title="第五步"></a>第五步</h3><p>   打开刚刚安装的PM2管理器并添加  app.js<br><img src="/images/music5.png" alt=" ">   </p><p><strong>到这里宝塔上就部署完了</strong></p><h1 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h1><h2 id="PC设置方式"><a href="#PC设置方式" class="headerlink" title="PC设置方式"></a>PC设置方式</h2><ol><li><p>打开系统地址：C:\Windows\System32\drivers\etc<br>部分Hosts文件因为安全组的原因无法打开或者保存，这种情况还请百度解决，毕竟我一个一个教有点费力<br>修改Hosts文件，向 hosts 文件添加两条规则（不会可以百度，我就不教了）<br><strong>上面这步可以跳过，如果下面的设置完了不能用的话再设置这个</strong></p></li><li><p>打开网易云客户端设置&gt;工具&gt;自定义代理&gt;HTTPS代理<br>服务器 输入你的服务器ip  端口 输入你开放的端口<br>用户名和密码不用管<br>点击确定，重启网易云</p></li></ol><h2 id="安卓端设置方法"><a href="#安卓端设置方法" class="headerlink" title="安卓端设置方法"></a>安卓端设置方法</h2><h3 id="安卓端WiFi下"><a href="#安卓端WiFi下" class="headerlink" title="安卓端WiFi下"></a>安卓端WiFi下</h3><p>手机设置 &gt; WLAN &gt; 网络设置 &gt; 高级选项 &gt; 代理<br><em>注意</em>：设置是你连接的那个wifi，一般在你连接的wifi边有一个感叹号，或者长按连接的wifi选择 修改网络<br>选择手动代理，主机名就是你的服务器IP 端口是你开放的端口（默认8080）</p><h3 id="安卓端流量下"><a href="#安卓端流量下" class="headerlink" title="安卓端流量下"></a>安卓端流量下</h3><p>建议配合Xndroid工具，最新版APP下载地址→<a href="https://github.com/XndroidDev/Xndroid/releases">传送门</a>，大致设置如下：<br>打开Xndroid &gt; 点击左侧Fqrouter &gt; 添加个人代理(只需要填服务器ip和端口即可) &gt; 代理列表配置项(将高级设置里面全部关掉) &gt; 软件右上角代理设置(只代理网易云音乐)</p><h3 id="IOS系统使用方法"><a href="#IOS系统使用方法" class="headerlink" title="IOS系统使用方法"></a>IOS系统使用方法</h3><p>IOS使用方法，对于不会设置的是挺复杂的，需要借助Shadowrocket工具。<br><strong>设置方法</strong><br>打开小火箭 &gt; 添加节点(类型选择HTTP，输入你的ip和端口，随便备注下，右上角完成即可) &gt; 编辑配置 &gt; 添加规则(类型选择USER-AGENT，选项选择网易云，用户代理输入NeteaseMusic*)，保存即可。</p><hr><p>设置完成后你还可以在右上角启动设置中，关掉xx-net和fqrouter里面的所有启动项，这样开启软件速度也会快很多。</p>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;说明&quot;&gt;&lt;a href=&quot;#说明&quot; class=&quot;headerlink&quot; title=&quot;说明&quot;&gt;&lt;/a&gt;说明&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;UnblockNeteaseMusic是一款可以给你解除网易云音乐海外限制并解锁变灰(无版权)歌曲的工具，让你可以听取客户端任何的歌曲，而不受到限制，此前该类似工具挺多的，不过貌似都不维护或者失效了，这里提到的项目更新很频繁，支持Windows、MacOS、安卓、IOS等设备，所以就分享一下使用方法。&lt;/p&gt;
&lt;/blockquote&gt;</summary>
    
    
    
    <category term="经验教程" scheme="https://blog.bugjava.cn/categories/%E7%BB%8F%E9%AA%8C%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="教程" scheme="https://blog.bugjava.cn/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="音乐" scheme="https://blog.bugjava.cn/tags/%E9%9F%B3%E4%B9%90/"/>
    
    <category term="宝塔" scheme="https://blog.bugjava.cn/tags/%E5%AE%9D%E5%A1%94/"/>
    
  </entry>
  
</feed>
