<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>caozhg&#39;s blog</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://www.caozhg.com/"/>
  <updated>2025-03-25T08:25:28.765Z</updated>
  <id>https://www.caozhg.com/</id>
  
  <author>
    <name>caozhg</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>centos7 安装 php7.4， 配置nginx，安装mongodb组件</title>
    <link href="https://www.caozhg.com/2025/03/25/centos7-%E5%AE%89%E8%A3%85-php7-4/"/>
    <id>https://www.caozhg.com/2025/03/25/centos7-安装-php7-4/</id>
    <published>2025-03-25T05:14:00.000Z</published>
    <updated>2025-03-25T08:25:28.765Z</updated>
    
    <content type="html"><![CDATA[<h1 id="安装-php7-4"><a href="#安装-php7-4" class="headerlink" title="安装 php7.4"></a>安装 php7.4</h1><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">#安装依赖</span><br><span class="line">yum install epel-release</span><br><span class="line"></span><br><span class="line">#启用PHP 7.4 Remi存储库并在CentOS 7上安装PHP 7.4</span><br><span class="line">#配置安装源</span><br><span class="line">yum -y install https://rpms.remirepo.net/enterprise/remi-release-7.rpm</span><br><span class="line">yum -y install yum-utils</span><br><span class="line"></span><br><span class="line">#设置安装版本</span><br><span class="line">yum-config-manager --enable remi-php74</span><br><span class="line"></span><br><span class="line">#安装php及拓展包</span><br><span class="line">yum install -y php php-cli php-fpm php-mysqlnd php-zip php-devel php-gd php-mcrypt php-mbstring php-curl php-xml php-pear php-bcmath php-json php-redis</span><br><span class="line"></span><br><span class="line">#查看php版本</span><br><span class="line">php -v</span><br><span class="line"></span><br><span class="line">#启动php</span><br><span class="line">systemctl start php-fpm</span><br><span class="line">systemctl enable php-fpm</span><br><span class="line"></span><br><span class="line">#php配置文件</span><br><span class="line">vi /etc/php.ini</span><br><span class="line"></span><br><span class="line">#修改php上传限制，默认为2M</span><br><span class="line">upload_max_filesize = 500M</span><br></pre></td></tr></table></figure><h1 id="php-nginx-配置"><a href="#php-nginx-配置" class="headerlink" title="php nginx 配置"></a>php nginx 配置</h1><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">server &#123;</span><br><span class="line">    listen       80;</span><br><span class="line">    server_name  localhost;</span><br><span class="line">    root         /home/www;</span><br><span class="line">    index        index.php index.html index.htm;</span><br><span class="line"></span><br><span class="line">    location / &#123;</span><br><span class="line">        try_files $uri $uri/ /index.php?$query_string;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    location ~ \.php$ &#123;</span><br><span class="line">        fastcgi_pass   127.0.0.1:9000;</span><br><span class="line">        fastcgi_index  index.php;</span><br><span class="line">        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;</span><br><span class="line">        include        fastcgi_params;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>php-fpm 指定 nginx 用户</p><p>vi /usr/local/php/etc/php-fpm.conf   # 修改为以下内容</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">user=nginx</span><br><span class="line">group=nginx</span><br></pre></td></tr></table></figure><h1 id="php-安装-mongodb"><a href="#php-安装-mongodb" class="headerlink" title="php 安装 mongodb"></a>php 安装 mongodb</h1><p>下方链接中找到适合 php 版本的 mongodb 组件。本文安装的 mongodb-1.5.4<br><a href="https://pecl.php.net/package/mongodb" target="_blank" rel="noopener">https://pecl.php.net/package/mongodb</a></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">wget http://pecl.php.net/get/mongodb-1.5.4.tgz</span><br><span class="line">tar -zxvf mongodb-1.5.4tgz</span><br><span class="line">cd mongodb-1.5.4</span><br><span class="line">phpize</span><br><span class="line">./configure</span><br><span class="line">make &amp;&amp; make install</span><br></pre></td></tr></table></figure><p>php 挂载 mongodb 组件</p><p>vi /etc/php.ini   # 最下方添加</p><figure class="highlight plain"><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">[mongodb]</span><br><span class="line">extension=mongodb.so</span><br></pre></td></tr></table></figure><p>重启 php-fpm</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl restart php-fpm</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;安装-php7-4&quot;&gt;&lt;a href=&quot;#安装-php7-4&quot; class=&quot;headerlink&quot; title=&quot;安装 php7.4&quot;&gt;&lt;/a&gt;安装 php7.4&lt;/h1&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;t
      
    
    </summary>
    
      <category term="linux" scheme="https://www.caozhg.com/categories/linux/"/>
    
    
      <category term="linux" scheme="https://www.caozhg.com/tags/linux/"/>
    
      <category term="centos 7" scheme="https://www.caozhg.com/tags/centos-7/"/>
    
      <category term="php" scheme="https://www.caozhg.com/tags/php/"/>
    
      <category term="nginx" scheme="https://www.caozhg.com/tags/nginx/"/>
    
      <category term="mongodb" scheme="https://www.caozhg.com/tags/mongodb/"/>
    
  </entry>
  
  <entry>
    <title>CentOS 7 设置系统时间的方法</title>
    <link href="https://www.caozhg.com/2025/03/24/CentOS-7-%E8%AE%BE%E7%BD%AE%E7%B3%BB%E7%BB%9F%E6%97%B6%E9%97%B4%E7%9A%84%E6%96%B9%E6%B3%95/"/>
    <id>https://www.caozhg.com/2025/03/24/CentOS-7-设置系统时间的方法/</id>
    <published>2025-03-24T07:00:00.000Z</published>
    <updated>2025-03-24T07:01:11.263Z</updated>
    
    <content type="html"><![CDATA[<p>设置系统时间为中国时区并启用NTP同步</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"># 安装ntp服务</span><br><span class="line">yum install ntp</span><br><span class="line"># 开机启动服务</span><br><span class="line">systemctl enable ntpd</span><br><span class="line"># 启动服务</span><br><span class="line">systemctl start ntpd</span><br><span class="line"># 更改时区</span><br><span class="line">timedatectl set-timezone Asia/Shanghai</span><br><span class="line"># 启用ntp同步</span><br><span class="line">timedatectl set-ntp yes</span><br><span class="line"># 同步时间</span><br><span class="line">ntpq -p</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;设置系统时间为中国时区并启用NTP同步&lt;/p&gt;
&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;li
      
    
    </summary>
    
      <category term="linux" scheme="https://www.caozhg.com/categories/linux/"/>
    
    
      <category term="linux" scheme="https://www.caozhg.com/tags/linux/"/>
    
      <category term="centos7" scheme="https://www.caozhg.com/tags/centos7/"/>
    
  </entry>
  
  <entry>
    <title>Docker 代理</title>
    <link href="https://www.caozhg.com/2025/03/22/Docker-%E4%BB%A3%E7%90%86/"/>
    <id>https://www.caozhg.com/2025/03/22/Docker-代理/</id>
    <published>2025-03-22T05:19:00.000Z</published>
    <updated>2025-03-22T05:19:29.877Z</updated>
    
    <content type="html"><![CDATA[<p>Docker守护进程指定代理</p><figure class="highlight plain"><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">mkdir -p /etc/systemd/system/docker.service.d/</span><br><span class="line">vi /etc/systemd/system/docker.service.d/http-proxy.conf</span><br></pre></td></tr></table></figure><p>写入代理</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[Service]</span><br><span class="line">Environment=&quot;HTTP_PROXY=http://127.0.0.1:7890&quot;</span><br><span class="line">Environment=&quot;HTTPS_PROXY=http://127.0.0.1:7890&quot;</span><br></pre></td></tr></table></figure><p>刷新配置，重启docker</p><figure class="highlight plain"><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">systemctl daemon-reload</span><br><span class="line">systemctl restart docker</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;Docker守护进程指定代理&lt;/p&gt;
&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2
      
    
    </summary>
    
      <category term="docker" scheme="https://www.caozhg.com/categories/docker/"/>
    
    
      <category term="linux" scheme="https://www.caozhg.com/tags/linux/"/>
    
      <category term="docker" scheme="https://www.caozhg.com/tags/docker/"/>
    
  </entry>
  
  <entry>
    <title>Dart Sass 替换 Node Sass</title>
    <link href="https://www.caozhg.com/2024/04/17/Dart-Sass%E6%9B%BF%E6%8D%A2Node-Sass/"/>
    <id>https://www.caozhg.com/2024/04/17/Dart-Sass替换Node-Sass/</id>
    <published>2024-04-17T01:05:00.000Z</published>
    <updated>2024-04-17T01:17:19.197Z</updated>
    
    <content type="html"><![CDATA[<p>node-sass 和 node.js 版本关联太紧了，如果这两个版本不匹配，就会起冲突，导致项目无法运行；另外因为网络原因，node-sass安装时经常无法下载，因此项目替换为 dart-sass。</p><h2 id="卸载-node-sass"><a href="#卸载-node-sass" class="headerlink" title="卸载 node-sass"></a>卸载 node-sass</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm uninstall node-sass</span><br></pre></td></tr></table></figure><h2 id="安装-dart-sass"><a href="#安装-dart-sass" class="headerlink" title="安装 dart-sass"></a>安装 dart-sass</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --dev sass</span><br></pre></td></tr></table></figure><p>如果项目中使用了 scss，则推荐使用 dart-sass 替换 scss 模块</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install node-sass@npm:dart-sass</span><br></pre></td></tr></table></figure><blockquote><p>注意：在替换完Node Sass后，需要用 <strong>::v-deep</strong> 代替 <strong>/deep/</strong> 和 <strong>&gt;&gt;&gt;</strong>  (注:如果在css中直接这么写是没用作用的) 来进行样式穿透。最重要原因是 vue 3.0 RFC中指定的写法，我们这么写之后可以尽量的最大程度减少升级到Vue3的复杂度。</p></blockquote>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;node-sass 和 node.js 版本关联太紧了，如果这两个版本不匹配，就会起冲突，导致项目无法运行；另外因为网络原因，node-sass安装时经常无法下载，因此项目替换为 dart-sass。&lt;/p&gt;
&lt;h2 id=&quot;卸载-node-sass&quot;&gt;&lt;a href=&quot;#
      
    
    </summary>
    
      <category term="前端" scheme="https://www.caozhg.com/categories/%E5%89%8D%E7%AB%AF/"/>
    
      <category term="nodejs" scheme="https://www.caozhg.com/categories/%E5%89%8D%E7%AB%AF/nodejs/"/>
    
    
      <category term="dart sass" scheme="https://www.caozhg.com/tags/dart-sass/"/>
    
      <category term="nodejs" scheme="https://www.caozhg.com/tags/nodejs/"/>
    
  </entry>
  
  <entry>
    <title>Java AES/ECB/PKCS7Padding</title>
    <link href="https://www.caozhg.com/2024/03/01/Java-AES-ECB-PKCS7Padding/"/>
    <id>https://www.caozhg.com/2024/03/01/Java-AES-ECB-PKCS7Padding/</id>
    <published>2024-03-01T03:13:00.000Z</published>
    <updated>2024-03-01T04:35:45.868Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>秘钥key的长度只能是16/24/32个字符。否则会报错：Key length not 128/192/256 bits.</p></blockquote><p><strong>pom.xml 引入</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- AES加密解密 PKCS7Padding--&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">&lt;groupId&gt;org.bouncycastle&lt;/groupId&gt;</span><br><span class="line">&lt;artifactId&gt;bcprov-jdk15&lt;/artifactId&gt;</span><br><span class="line">&lt;version&gt;1.44&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure><p><strong>AES加密</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * AES加密</span><br><span class="line"> * AES/ECB/PKCS7Padding</span><br><span class="line"> */</span><br><span class="line">public static String encrypt(String input, String key)  throws Exception &#123;</span><br><span class="line"></span><br><span class="line">    SecretKeySpec skey = new SecretKeySpec(key.getBytes(), &quot;AES&quot;);</span><br><span class="line">    Cipher cipher = Cipher.getInstance(&quot;AES/ECB/PKCS7Padding&quot;);</span><br><span class="line">    cipher.init(Cipher.ENCRYPT_MODE, skey);</span><br><span class="line">    byte[] crypted = cipher.doFinal(input.getBytes());</span><br><span class="line"></span><br><span class="line">    return new String(Base64.encodeBase64(crypted));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>AES解密</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * AES解密</span><br><span class="line"> * AES/ECB/PKCS7Padding</span><br><span class="line"> */</span><br><span class="line">public static String decrypt(String input, String key) throws Exception &#123;</span><br><span class="line"></span><br><span class="line">    SecretKeySpec skey = new SecretKeySpec(key.getBytes(), &quot;AES&quot;);</span><br><span class="line">    Cipher cipher = Cipher.getInstance(&quot;AES/ECB/PKCS7Padding&quot;);</span><br><span class="line">    cipher.init(Cipher.DECRYPT_MODE, skey);</span><br><span class="line">    byte[] output = cipher.doFinal(Base64.decodeBase64(input));</span><br><span class="line"></span><br><span class="line">    return new String(output);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;blockquote&gt;
&lt;p&gt;秘钥key的长度只能是16/24/32个字符。否则会报错：Key length not 128/192/256 bits.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;pom.xml 引入&lt;/strong&gt;&lt;/p&gt;
&lt;figure c
      
    
    </summary>
    
      <category term="java" scheme="https://www.caozhg.com/categories/java/"/>
    
    
      <category term="java" scheme="https://www.caozhg.com/tags/java/"/>
    
      <category term="AES/ECB/PKCS7Padding" scheme="https://www.caozhg.com/tags/AES-ECB-PKCS7Padding/"/>
    
  </entry>
  
  <entry>
    <title>Java lambda 常用表达式</title>
    <link href="https://www.caozhg.com/2024/02/29/Java-lambda-%E5%B8%B8%E7%94%A8/"/>
    <id>https://www.caozhg.com/2024/02/29/Java-lambda-常用/</id>
    <published>2024-02-29T03:02:00.000Z</published>
    <updated>2024-02-29T08:38:09.192Z</updated>
    
    <content type="html"><![CDATA[<p> Collection、List、Set、Map 之间各种类型转化<br> <a id="more"></a></p><ol><li>将 <code>Collection&lt;OrderItem&gt;</code> 转化为 <code>List&lt;OrderItem&gt;</code></li><li>将 <code>Collection&lt;OrderItem&gt;</code> 转化为 <code>Set&lt;OrderItem&gt;</code></li><li>将 <code>List&lt;OrderItem&gt;</code> 转化为 <code>List&lt;Long&gt;</code></li><li>将 <code>Set&lt;OrderItem&gt;</code> 转化为 <code>Set&lt;Long&gt;</code></li><li>将 <code>Collection&lt;OrderItem&gt;</code> 转化为 <code>List&lt;Long&gt;</code></li><li>将 <code>Collection&lt;OrderItem&gt;</code> 转化为 <code>Set&lt;Long&gt;</code></li><li>从 <code>Collection&lt;OrderItem&gt;</code> 中提取 Key, Map 的 Value 就是类型 OrderItem</li><li>从 <code>Collection&lt;OrderItem&gt;</code> 中提取 Key, Map 的 Value 根据 OrderItem 类型进行转化。</li><li>将 <code>Map&lt;Long, OrderItem&gt;</code> 中的value 转化为 <code>Map&lt;Long, Double&gt;</code></li><li>value 转化时，lamada表达式可以使用<code>(v)-&gt;{}</code>， 也可以使用 <code>(k，v)-&gt;{ }</code>。</li></ol><h1 id="Collection-转化为-Map"><a href="#Collection-转化为-Map" class="headerlink" title="Collection 转化为 Map"></a>Collection 转化为 Map</h1><p>由于 List 和 Set 是 Collection 类型的子类，所以只需要实现Collection 类型转化为 Map 类型即可。 Collection转化为 Map 共分两个方法</p><ol><li>从 <code>Collection&lt;OrderItem&gt;</code> 到 <code>Map&lt;Key, OrderItem&gt;</code>，提取 Key, Map 的 Value 就是类型 OrderItem</li><li>从 <code>Collection&lt;OrderItem&gt;</code> 到 <code>Map&lt;Key，Value&gt;</code>，提取 Key, Map 的 Value 根据 OrderItem 类型进行转化。</li></ol><p><strong>使用样例</strong></p><p>代码示例中把 <code>Set&lt;OrderItem&gt;</code> 转化为 <code>Map&lt;Long, OrderItem&gt;</code> 和 <code>Map&lt;Long ,Double&gt;</code>。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">@Test</span><br><span class="line">public void testToMap() &#123;</span><br><span class="line">    Collection&lt;OrderItem&gt; collection = coll;</span><br><span class="line">    Set&lt;OrderItem&gt; set = toSet(collection);</span><br><span class="line"></span><br><span class="line">    Map&lt;Long, OrderItem&gt; map = toMap(set, OrderItem::getOrderId);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@Test</span><br><span class="line">public void testToMapV2() &#123;</span><br><span class="line">    Collection&lt;OrderItem&gt; collection = coll;</span><br><span class="line">    Set&lt;OrderItem&gt; set = toSet(collection);</span><br><span class="line"></span><br><span class="line">    Map&lt;Long, Double&gt; map = toMap(set, OrderItem::getOrderId, OrderItem::getActPrice);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>代码展示</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">public static &lt;T, K&gt; Map&lt;K, T&gt; toMap(Collection&lt;T&gt; collection, </span><br><span class="line">Function&lt;? super T, ? extends K&gt; keyMapper) &#123;</span><br><span class="line">    return toMap(collection, keyMapper, Function.identity());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static &lt;T, K, V&gt; Map&lt;K, V&gt; toMap(Collection&lt;T&gt; collection,</span><br><span class="line">                                        Function&lt;? super T, ? extends K&gt; keyFunction,</span><br><span class="line">                                        Function&lt;? super T, ? extends V&gt; valueFunction) &#123;</span><br><span class="line">    return toMap(collection, keyFunction, valueFunction, pickSecond());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static &lt;T, K, V&gt; Map&lt;K, V&gt; toMap(Collection&lt;T&gt; collection,</span><br><span class="line">                                        Function&lt;? super T, ? extends K&gt; keyFunction,</span><br><span class="line">                                        Function&lt;? super T, ? extends V&gt; valueFunction,</span><br><span class="line">                                        BinaryOperator&lt;V&gt; mergeFunction) &#123;</span><br><span class="line">    if (CollectionUtils.isEmpty(collection)) &#123;</span><br><span class="line">        return new HashMap&lt;&gt;(0);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    return collection.stream().collect(Collectors.toMap(keyFunction, valueFunction, mergeFunction));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static &lt;T&gt; BinaryOperator&lt;T&gt; pickFirst() &#123;</span><br><span class="line">    return (k1, k2) -&gt; k1;</span><br><span class="line">&#125;</span><br><span class="line">public static &lt;T&gt; BinaryOperator&lt;T&gt; pickSecond() &#123;</span><br><span class="line">    return (k1, k2) -&gt; k2;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="转换-Map-的-Value"><a href="#转换-Map-的-Value" class="headerlink" title="转换 Map 的 Value"></a>转换 Map 的 Value</h1><ol><li>将 <code>Map&lt;Long, OrderItem&gt;</code> 中的value 转化为 <code>Map&lt;Long, Double&gt;</code></li><li>value 转化时，lamada表达式可以使用 <code>(v)-&gt;{}</code>， 也可以使用 <code>(k，v)-&gt;{ }</code>。</li></ol><p><strong>测试样例</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">@Test</span><br><span class="line">public void testConvertValue() &#123;</span><br><span class="line">    Collection&lt;OrderItem&gt; collection = coll;</span><br><span class="line">    Set&lt;OrderItem&gt; set = toSet(collection);</span><br><span class="line"></span><br><span class="line">    Map&lt;Long, OrderItem&gt; map = toMap(set, OrderItem::getOrderId);</span><br><span class="line"></span><br><span class="line">    Map&lt;Long, Double&gt; orderId2Price = convertMapValue(map, item -&gt; item.getActPrice());</span><br><span class="line">    Map&lt;Long, String&gt; orderId2Token = convertMapValue(map, (id, item) -&gt; id + item.getName());</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>代码展示</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">public static &lt;K, V, C&gt; Map&lt;K, C&gt; convertMapValue(Map&lt;K, V&gt; map, </span><br><span class="line">                        BiFunction&lt;K, V, C&gt; valueFunction,</span><br><span class="line">                        BinaryOperator&lt;C&gt; mergeFunction) &#123;</span><br><span class="line">    if (isEmpty(map)) &#123;</span><br><span class="line">        return new HashMap&lt;&gt;();</span><br><span class="line">    &#125;</span><br><span class="line">    return map.entrySet().stream().collect(Collectors.toMap(</span><br><span class="line">            e -&gt; e.getKey(),</span><br><span class="line">            e -&gt; valueFunction.apply(e.getKey(), e.getValue()),</span><br><span class="line">            mergeFunction</span><br><span class="line">    ));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static &lt;K, V, C&gt; Map&lt;K, C&gt; convertMapValue(Map&lt;K, V&gt; originMap, BiFunction&lt;K, V, C&gt; valueConverter) &#123;</span><br><span class="line">    return convertMapValue(originMap, valueConverter, Lambdas.pickSecond());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static &lt;T&gt; BinaryOperator&lt;T&gt; pickFirst() &#123;</span><br><span class="line">    return (k1, k2) -&gt; k1;</span><br><span class="line">&#125;</span><br><span class="line">public static &lt;T&gt; BinaryOperator&lt;T&gt; pickSecond() &#123;</span><br><span class="line">    return (k1, k2) -&gt; k2;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="Collection-和-List、Set-的转化"><a href="#Collection-和-List、Set-的转化" class="headerlink" title="Collection 和 List、Set 的转化"></a>Collection 和 List、Set 的转化</h1><ol><li>将 <code>Collection&lt;OrderItem&gt;</code> 转化为 <code>List&lt;OrderItem&gt;</code></li><li>将 <code>Collection&lt;OrderItem&gt;</code> 转化为 <code>Set&lt;OrderItem&gt;</code></li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">public static &lt;T&gt; List&lt;T&gt; toList(Collection&lt;T&gt; collection) &#123;</span><br><span class="line">    if (collection == null) &#123;</span><br><span class="line">        return new ArrayList&lt;&gt;();</span><br><span class="line">    &#125;</span><br><span class="line">    if (collection instanceof List) &#123;</span><br><span class="line">        return (List&lt;T&gt;) collection;</span><br><span class="line">    &#125;</span><br><span class="line">    return collection.stream().collect(Collectors.toList());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static &lt;T&gt; Set&lt;T&gt; toSet(Collection&lt;T&gt; collection) &#123;</span><br><span class="line">    if (collection == null) &#123;</span><br><span class="line">        return new HashSet&lt;&gt;();</span><br><span class="line">    &#125;</span><br><span class="line">    if (collection instanceof Set) &#123;</span><br><span class="line">        return (Set&lt;T&gt;) collection;</span><br><span class="line">    &#125;</span><br><span class="line">    return collection.stream().collect(Collectors.toSet());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>测试样例</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">//将集合 Collection 转化为 List</span><br><span class="line">@Test</span><br><span class="line">public void testToList() &#123;</span><br><span class="line">    Collection&lt;OrderItem&gt; collection = coll;</span><br><span class="line">    List&lt;OrderItem&gt; list = toList(coll);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//将集合 Collection 转化为 Set</span><br><span class="line">@Test</span><br><span class="line">public void testToSet() &#123;</span><br><span class="line">    Collection&lt;OrderItem&gt; collection = coll;</span><br><span class="line">    Set&lt;OrderItem&gt; set = toSet(collection);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>List和 Set 是 Collection 集合类型的子类，所以无需再转化。</p><h1 id="List、Set-类型之间的转换"><a href="#List、Set-类型之间的转换" class="headerlink" title="List、Set 类型之间的转换"></a>List、Set 类型之间的转换</h1><p>业务中有时候需要将 <code>List&lt;A&gt;</code> 转化为 <code>List&lt;B&gt;</code>。如何实现工具类呢？</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">public static &lt;T, R&gt; List&lt;R&gt; map(List&lt;T&gt; collection, Function&lt;T, R&gt; mapper) &#123;</span><br><span class="line">    return collection.stream().map(mapper).collect(Collectors.toList());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static &lt;T, R&gt; Set&lt;R&gt; map(Set&lt;T&gt; collection, Function&lt;T, R&gt; mapper) &#123;</span><br><span class="line">    return collection.stream().map(mapper).collect(Collectors.toSet());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static &lt;T, R&gt; List&lt;R&gt; mapToList(Collection&lt;T&gt; collection, Function&lt;T, R&gt; mapper) &#123;</span><br><span class="line">    return collection.stream().map(mapper).collect(Collectors.toList());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static &lt;T, R&gt; Set&lt;R&gt; mapToSet(Collection&lt;T&gt; collection, Function&lt;T, R&gt; mapper) &#123;</span><br><span class="line">    return collection.stream().map(mapper).collect(Collectors.toSet());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>测试样例</strong></p><ol><li>将 <code>List&lt;OrderItem&gt;</code> 转化为 <code>List&lt;Long&gt;</code></li><li>将 <code>Set&lt;OrderItem&gt;</code> 转化为 <code>Set&lt;Long&gt;</code></li><li>将 <code>Collection&lt;OrderItem&gt;</code> 转化为 <code>List&lt;Long&gt;</code></li><li>将 <code>Collection&lt;OrderItem&gt;</code> 转化为 <code>Set&lt;Long&gt;</code></li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">@Test</span><br><span class="line">public void testMapToList() &#123;</span><br><span class="line">    Collection&lt;OrderItem&gt; collection = coll;</span><br><span class="line">    List&lt;OrderItem&gt; list = toList(coll);</span><br><span class="line">    List&lt;Long&gt; orderIdList = map(list, (item) -&gt; item.getOrderId());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@Test</span><br><span class="line">public void testMapToSet() &#123;</span><br><span class="line">    Collection&lt;OrderItem&gt; collection = coll;</span><br><span class="line">    Set&lt;OrderItem&gt; set = toSet(coll);</span><br><span class="line">    Set&lt;Long&gt; orderIdSet = map(set, (item) -&gt; item.getOrderId());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@Test</span><br><span class="line">public void testMapToList2() &#123;</span><br><span class="line">    Collection&lt;OrderItem&gt; collection = coll;</span><br><span class="line">    List&lt;Long&gt; orderIdList = mapToList(collection, (item) -&gt; item.getOrderId());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@Test</span><br><span class="line">public void testMapToSetV2() &#123;</span><br><span class="line">    Collection&lt;OrderItem&gt; collection = coll;</span><br><span class="line">    Set&lt;Long&gt; orderIdSet = mapToSet(collection, (item) -&gt; item.getOrderId());</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;p&gt; Collection、List、Set、Map 之间各种类型转化&lt;br&gt;
    
    </summary>
    
      <category term="java" scheme="https://www.caozhg.com/categories/java/"/>
    
    
      <category term="java" scheme="https://www.caozhg.com/tags/java/"/>
    
  </entry>
  
  <entry>
    <title>npm CDN加速，替代 unpkg、jsdelivr</title>
    <link href="https://www.caozhg.com/2023/12/15/npm-CDN%E5%8A%A0%E9%80%9F%EF%BC%8C%E6%9B%BF%E4%BB%A3NPM/"/>
    <id>https://www.caozhg.com/2023/12/15/npm-CDN加速，替代NPM/</id>
    <published>2023-12-15T02:31:00.000Z</published>
    <updated>2023-12-15T02:40:38.711Z</updated>
    
    <content type="html"><![CDATA[<h2 id="经典老牌的CDN加速"><a href="#经典老牌的CDN加速" class="headerlink" title="经典老牌的CDN加速"></a>经典老牌的CDN加速</h2><ul><li>unpkg.com</li><li>cdn.jsdelivr.net</li><li>cdn.jsdelivr.net</li></ul><p><strong>使用方法：</strong>直接进官网，搜NPM包名使用。</p><p><strong>缺点：</strong>有时候不是很稳定，而且国内有些地方没法访问，jsdelivr曾经被用来结合github做免费CDN加速的图床存博客配图，不过之前遇到过使用jsdelivr直接访问不了的情况。</p><h2 id="国内能用的"><a href="#国内能用的" class="headerlink" title="国内能用的"></a>国内能用的</h2><ul><li>BootCDN: <a href="http://www.bootcdn.cn" target="_blank" rel="noopener">www.bootcdn.cn</a></li><li>七牛云: <a href="http://www.staticfile.org" target="_blank" rel="noopener">www.staticfile.org</a></li><li>360: cdn.baomitu.com</li><li>字节跳动: cdn.bytedance.com</li></ul><p><strong>使用方法：</strong>直接进官网，搜NPM包名使用。</p><p><strong>缺点：</strong>上面几个的CDN并不全，很多NPM上的包 在这些CDN上是找不到的。原因是，它们都是从CDNJS上同步的数据，CDNJS 并不会把所有的 NPM 包进行同步，所以当你需要的一些NPM包没有在CDNJS上面，你就用不了上面这些国内CDN了。</p><h2 id="推荐"><a href="#推荐" class="headerlink" title="推荐"></a>推荐</h2><ul><li>饿了么1：github.elemecdn.com（使用可参考UNPKG）</li><li>饿了么2：npm.elemecdn.com（使用可参考UNPKG）</li><li>知乎：unpkg.zhimg.com（使用可参考UNPKG）</li><li>jsd.onmicrosoft.cn(回源 jsDelivr，使用可参考jsDelivr)</li><li>npm.onmicrosoft.cn (回源 UNPKG，使用可参考UNPKG)</li><li>cdnjs.onmicrosoft.cn (回源 cdnjs，使用可参考cdnjs)</li></ul><p><strong>使用方法：</strong>饿了么跟知乎的不要直接点链接进网站，直接进是显示403报错。直接参考上面unpkg、jsdelivr等的使用方法，更换CDN的域名就行了。</p><p><strong>优点：</strong>跟BootCDN、七牛云、360、字节跳动的那几个相比较，CDN包更全一些，能搜到的NPM包与unpkg上的基本一致。</p><h2 id="自建-jsDelivr-反向代理"><a href="#自建-jsDelivr-反向代理" class="headerlink" title="自建 jsDelivr 反向代理"></a>自建 jsDelivr 反向代理</h2><h3 id="使用-nginx-自建"><a href="#使用-nginx-自建" class="headerlink" title="使用 nginx 自建"></a>使用 nginx 自建</h3><blockquote><p><a href="https://hostloc.com/thread-1020655-1-1.html" target="_blank" rel="noopener">https://hostloc.com/thread-1020655-1-1.html</a></p></blockquote><h3 id="使用宝塔自建"><a href="#使用宝塔自建" class="headerlink" title="使用宝塔自建"></a>使用宝塔自建</h3><blockquote><p><a href="https://www.kezez.com/archives/140.html" target="_blank" rel="noopener">https://www.kezez.com/archives/140.html</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;经典老牌的CDN加速&quot;&gt;&lt;a href=&quot;#经典老牌的CDN加速&quot; class=&quot;headerlink&quot; title=&quot;经典老牌的CDN加速&quot;&gt;&lt;/a&gt;经典老牌的CDN加速&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;unpkg.com&lt;/li&gt;
&lt;li&gt;cdn.jsdelivr.
      
    
    </summary>
    
      <category term="工具" scheme="https://www.caozhg.com/categories/%E5%B7%A5%E5%85%B7/"/>
    
    
      <category term="npm" scheme="https://www.caozhg.com/tags/npm/"/>
    
  </entry>
  
  <entry>
    <title>springboot 引入外部 jar</title>
    <link href="https://www.caozhg.com/2023/11/17/springboot-%E5%BC%95%E5%85%A5%E5%A4%96%E9%83%A8-jar/"/>
    <id>https://www.caozhg.com/2023/11/17/springboot-引入外部-jar/</id>
    <published>2023-11-17T02:26:00.000Z</published>
    <updated>2023-11-17T02:51:12.432Z</updated>
    
    <content type="html"><![CDATA[<ol><li><p>项目根目录添加 lib 目录，并放入需要引用的 jar</p></li><li><p>在 pom 中引入</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;masmgc.sdk&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;sms&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;1.0.3-SNAPSHOT&lt;/version&gt;</span><br><span class="line">    &lt;scope&gt;system&lt;/scope&gt;</span><br><span class="line">    &lt;systemPath&gt;$&#123;project.basedir&#125;/lib/masmgc.sdk.sms-1.0.3-SNAPSHOT.jar&lt;/systemPath&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure></li><li><p>打包配置</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">&lt;build&gt;</span><br><span class="line">    &lt;plugins&gt;</span><br><span class="line">        &lt;plugin&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;</span><br><span class="line">            &lt;configuration&gt;</span><br><span class="line">                &lt;!-- 在打包时将引用的外部jar引入到当前项目包中--&gt;</span><br><span class="line">                &lt;includeSystemScope&gt;true&lt;/includeSystemScope&gt;</span><br><span class="line">            &lt;/configuration&gt;</span><br><span class="line">        &lt;/plugin&gt;</span><br><span class="line">    &lt;/plugins&gt;</span><br><span class="line">&lt;/build&gt;</span><br><span class="line">&lt;resources&gt;</span><br><span class="line">    &lt;resource&gt;</span><br><span class="line">        &lt;!-- directory 表示取该目录下的文件 --&gt;</span><br><span class="line">        &lt;directory&gt;lib&lt;/directory&gt;</span><br><span class="line">        &lt;!--targetPath 指定打包到哪个目录下  默认是放到class目录下--&gt;</span><br><span class="line">        &lt;targetPath&gt;/BOOT-INF/lib/&lt;/targetPath&gt;</span><br><span class="line">        &lt;!-- 取符合格式的所有文件  *代表全部 --&gt;</span><br><span class="line">        &lt;includes&gt;</span><br><span class="line">            &lt;include&gt;**/*.jar&lt;/include&gt;</span><br><span class="line">        &lt;/includes&gt;</span><br><span class="line">    &lt;/resource&gt;</span><br><span class="line">&lt;/resources&gt;</span><br></pre></td></tr></table></figure></li></ol>]]></content>
    
    <summary type="html">
    
      
      
        &lt;ol&gt;
&lt;li&gt;&lt;p&gt;项目根目录添加 lib 目录，并放入需要引用的 jar&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;在 pom 中引入&lt;/p&gt;
&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;s
      
    
    </summary>
    
      <category term="java" scheme="https://www.caozhg.com/categories/java/"/>
    
    
      <category term="maven" scheme="https://www.caozhg.com/tags/maven/"/>
    
      <category term="springboot" scheme="https://www.caozhg.com/tags/springboot/"/>
    
  </entry>
  
  <entry>
    <title>jasypt-spring-boot application.yml文件敏感信息加密</title>
    <link href="https://www.caozhg.com/2023/11/07/application-yml%E6%96%87%E4%BB%B6%E6%95%8F%E6%84%9F%E4%BF%A1%E6%81%AF%E5%8A%A0%E5%AF%86/"/>
    <id>https://www.caozhg.com/2023/11/07/application-yml文件敏感信息加密/</id>
    <published>2023-11-07T02:30:00.000Z</published>
    <updated>2023-11-07T02:45:49.770Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p><strong>注意</strong></p><p>springboot 3.0 以后的版本，使用 jasypt-spring-boot-starter 3.0.5 以后的版本。</p></blockquote><h3 id="导入依赖"><a href="#导入依赖" class="headerlink" title="导入依赖"></a>导入依赖</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;  </span><br><span class="line">    &lt;groupId&gt;com.github.ulisesbocchio&lt;/groupId&gt;  </span><br><span class="line">    &lt;artifactId&gt;jasypt-spring-boot-starter&lt;/artifactId&gt;  </span><br><span class="line">    &lt;version&gt;3.0.5&lt;/version&gt;  </span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure><h3 id="使用-jasypt"><a href="#使用-jasypt" class="headerlink" title="使用 jasypt"></a>使用 jasypt</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">jasypt:  </span><br><span class="line">  encryptor:  </span><br><span class="line">    password: sdjsdbshdbfuasd  </span><br><span class="line">    property:  </span><br><span class="line">      prefix: ENC(</span><br><span class="line">      suffix: )</span><br></pre></td></tr></table></figure><blockquote><p>password 加密密码<br>prefix和suffix是默认值，支持自定义，自动解密使用</p></blockquote><p>jasypt 提供了一个工具类接口，StringEncryptor，这个接口提供了加解密方法。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">public interface StringEncryptor &#123;  </span><br><span class="line">  </span><br><span class="line">    /**  </span><br><span class="line">    * 加密输入信息  </span><br><span class="line">    *  </span><br><span class="line">    * @param 要加密的信息  </span><br><span class="line">    * @return 加密结果  </span><br><span class="line">    */  </span><br><span class="line">    public String encrypt(String message);  </span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    /**  </span><br><span class="line">    * 解密加密信息  </span><br><span class="line">    *  </span><br><span class="line">    * @param 加密信息（encryptedMessage） 要解密的加密信息  </span><br><span class="line">    * @return 解密结果  </span><br><span class="line">    */  </span><br><span class="line">    public String decrypt(String encryptedMessage);  </span><br><span class="line">  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>我们在 test 测试类中，将要进行加密的文本使用encrypt方法进行加密</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">@SpringBootTest  </span><br><span class="line">@Slf4j  </span><br><span class="line">class JasryptApplicationTests &#123;  </span><br><span class="line">  </span><br><span class="line">    @Autowired  </span><br><span class="line">    private StringEncryptor stringEncryptor;  </span><br><span class="line"></span><br><span class="line">    @Test  </span><br><span class="line">    void contextLoads() &#123;  </span><br><span class="line">        String username = stringEncryptor.encrypt(&quot;root&quot;);  </span><br><span class="line">        String password = stringEncryptor.encrypt(&quot;root&quot;);  </span><br><span class="line">        log.info(&quot;username encrypt is &#123;&#125;&quot;, username);  </span><br><span class="line">        log.info(&quot;password encrypt is &#123;&#125;&quot;, password);  </span><br><span class="line">        log.info(&quot;username decrypt is &#123;&#125;&quot;, stringEncryptor.decrypt(username));  </span><br><span class="line">        log.info(&quot;password decrypt is &#123;&#125;&quot;, stringEncryptor.decrypt(password));  </span><br><span class="line">    &#125;  </span><br><span class="line">  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>上边代码，加密的内容是，MySQL的用户名和密码，同时对它们进行加密和解密。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">2023-10-23T08:29:31.321+08:00  INFO 9489 --- [           main] c.e.jasrypt.JasryptApplicationTests      : username encrypt is 61zSoixtNayUruXt5x84kEKO9jGnZObTGCa1+k5Yg9F7qSUiZvp5fG31AMuVqrot</span><br><span class="line">2023-10-23T08:29:31.321+08:00  INFO 9489 --- [           main] c.e.jasrypt.JasryptApplicationTests      : password encrypt is a6snCZCkbQFKkQqxN2bS18ags04yZxH+THwIL5RjGocEjG9sLkJvvasPFFVxEBWv</span><br><span class="line">2023-10-23T08:29:31.323+08:00  INFO 9489 --- [           main] c.e.jasrypt.JasryptApplicationTests      : username decrypt is root</span><br><span class="line">2023-10-23T08:29:31.330+08:00  INFO 9489 --- [           main] c.e.jasrypt.JasryptApplicationTests      : password decrypt is root</span><br></pre></td></tr></table></figure><p>加密默认使用的是PBEWITHHMACSHA512ANDAES_256加密 我们将密文，替换到数据源，注意别忘了加上前缀和后缀，如上边代码，配置：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">spring:  </span><br><span class="line">  datasource:  </span><br><span class="line">    driver-class-name: com.mysql.cj.jdbc.Driver  </span><br><span class="line">    url: jdbc:mysql://localhost:3306/jasypt_test?        useUnicode=true&amp;zeroDateTimeBehavior=convertToNull&amp;autoReconnect=true&amp;characterEncoding=utf-8</span><br><span class="line">    username: ENC(61zSoixtNayUruXt5x84kEKO9jGnZObTGCa1+k5Yg9F7qSUiZvp5fG31AMuVqrot) </span><br><span class="line">    password: ENC(a6snCZCkbQFKkQqxN2bS18ags04yZxH+THwIL5RjGocEjG9sLkJvvasPFFVxEBWv)</span><br></pre></td></tr></table></figure><p>这个时候就已经完成了，但是官方不建议我们将加密密码放到配置文件中，我们应作为系统属性、命令行参数或环境变量传递，只要其名称是<code>jasypt.encryptor.password</code>，就能正常工作。</p><p>我们可以将项目打为<code>jar包</code>然后使用<code>java -jar</code>命令。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -jar jasrypt-0.0.1-SNAPSHOT.jar --jasypt.encryptor.password=加密密码</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;springboot 3.0 以后的版本，使用 jasypt-spring-boot-starter 3.0.5 以后的版本。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;导入依赖&quot;&gt;&lt;
      
    
    </summary>
    
      <category term="java" scheme="https://www.caozhg.com/categories/java/"/>
    
    
      <category term="java" scheme="https://www.caozhg.com/tags/java/"/>
    
      <category term="spring boot" scheme="https://www.caozhg.com/tags/spring-boot/"/>
    
      <category term="jasypt" scheme="https://www.caozhg.com/tags/jasypt/"/>
    
  </entry>
  
  <entry>
    <title>frp linux 部署</title>
    <link href="https://www.caozhg.com/2023/10/30/frp-linux-%E9%83%A8%E7%BD%B2/"/>
    <id>https://www.caozhg.com/2023/10/30/frp-linux-部署/</id>
    <published>2023-10-30T06:57:00.000Z</published>
    <updated>2023-10-30T07:28:44.160Z</updated>
    
    <content type="html"><![CDATA[<h3 id="安装服务端"><a href="#安装服务端" class="headerlink" title="安装服务端"></a>安装服务端</h3><ul><li>下载 frp 安装包</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget https://github.com/fatedier/frp/releases/download/v0.46.1/frp_0.46.1_linux_amd64.tar.gz</span><br></pre></td></tr></table></figure><ul><li>解压</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tar -xvf frp_0.46.1_linux_amd64</span><br></pre></td></tr></table></figure><h3 id="配置服务端"><a href="#配置服务端" class="headerlink" title="配置服务端"></a>配置服务端</h3><ul><li>编辑配置文件</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">bind_port = 7000 # 端口</span><br><span class="line">token=123456 # 密码</span><br><span class="line">vhost_http_port = 7000 #自定义设置的http访问端口</span><br><span class="line">vhost_https_port = 7000 #自定义设置的https访问端口</span><br><span class="line"></span><br><span class="line">dashboard_port = 7500 #控制面板访问端口</span><br><span class="line">dashboard_user = admin #控制面板访问用户名</span><br><span class="line">dashboard_pwd = 123456 #控制面板访问密码</span><br></pre></td></tr></table></figure><ul><li>执行启动命令</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">frps -c frps.ini</span><br></pre></td></tr></table></figure><h3 id="配置客户端"><a href="#配置客户端" class="headerlink" title="配置客户端"></a>配置客户端</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">[common]</span><br><span class="line">server_addr = 服务器IP</span><br><span class="line">server_port = 7000</span><br><span class="line"># FRP 身份验证 与 服务端一致</span><br><span class="line">token = 密码</span><br><span class="line"></span><br><span class="line">[web]</span><br><span class="line">type = http</span><br><span class="line">local_port = 本机http服务端口</span><br><span class="line">custom_domains = 访问域名</span><br></pre></td></tr></table></figure><h3 id="frps-服务端开机自启动"><a href="#frps-服务端开机自启动" class="headerlink" title="frps 服务端开机自启动"></a>frps 服务端开机自启动</h3><ul><li>安装 systemd</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install systemd</span><br></pre></td></tr></table></figure><ul><li>在systemd配置目录/usr/lib/systemd/system下创建frps.service文件</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">[Unit]</span><br><span class="line"># 服务名称，可自定义</span><br><span class="line">Description = frps server</span><br><span class="line">After = network.target syslog.target</span><br><span class="line">Wants = network.target</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type = simple</span><br><span class="line"># 启动frps的命令，需修改为您的frps的安装路径</span><br><span class="line">ExecStart = /path/to/frps -c /path/to/frps.ini</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy = multi-user.target</span><br></pre></td></tr></table></figure><ul><li>使用systemd命令，管理frps</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"># 启动frp</span><br><span class="line">systemctl start frps</span><br><span class="line"># frp跟随Linux自启</span><br><span class="line">systemctl enable frps</span><br><span class="line"># 停止frp</span><br><span class="line">systemctl stop frps</span><br><span class="line"># 重启frp</span><br><span class="line">systemctl restart frps</span><br><span class="line"># 查看frp状态</span><br><span class="line">systemctl status frps</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;ul&gt;
&lt;li&gt;下载 frp 安装包&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;highlight plain
      
    
    </summary>
    
    
      <category term="frp" scheme="https://www.caozhg.com/tags/frp/"/>
    
      <category term="内网穿透" scheme="https://www.caozhg.com/tags/%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F/"/>
    
  </entry>
  
  <entry>
    <title>logback+logstash日志采集</title>
    <link href="https://www.caozhg.com/2023/06/08/logback-logstash%E6%97%A5%E5%BF%97%E9%87%87%E9%9B%86/"/>
    <id>https://www.caozhg.com/2023/06/08/logback-logstash日志采集/</id>
    <published>2023-06-08T05:31:00.000Z</published>
    <updated>2023-06-08T05:40:06.684Z</updated>
    
    <content type="html"><![CDATA[<p>logstash与logback的集成，实现日志信息直接通过logstash发送到ES</p><a id="more"></a><p>配置logback-spring.xml</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&lt;property name=&quot;CONSOLE_LOG_PATTERN&quot; value=&quot;%d&#123;yyyy-MM-dd HH:mm:ss.SSS&#125;|%mdc&#123;tid&#125;|%thread|%level|%logger|%msg%n&quot;/&gt;</span><br><span class="line"></span><br><span class="line">&lt;appender name=&quot;LOGSTASH&quot; class=&quot;net.logstash.logback.appender.LogstashTcpSocketAppender&quot;&gt;</span><br><span class="line">    &lt;destination&gt;192.168.2.254:5044&lt;/destination&gt;</span><br><span class="line">    &lt;encoder charset=&quot;UTF-8&quot; class=&quot;net.logstash.logback.encoder.LogstashEncoder&quot;/&gt;</span><br><span class="line">&lt;/appender&gt;</span><br><span class="line"></span><br><span class="line">&lt;root level=&quot;INFO&quot;&gt;</span><br><span class="line">    &lt;appender-ref ref=&quot;LOGSTASH&quot;/&gt;</span><br><span class="line">&lt;/root&gt;</span><br></pre></td></tr></table></figure><p>配置logstash-xxx.conf</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">input &#123;</span><br><span class="line">  tcp &#123;</span><br><span class="line">    mode =&gt; &quot;server&quot;</span><br><span class="line">host =&gt; &quot;0.0.0.0&quot;</span><br><span class="line">    port =&gt; 5044</span><br><span class="line">codec =&gt; json_lines</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">output &#123;</span><br><span class="line">  elasticsearch &#123;</span><br><span class="line">    hosts =&gt; [&quot;http://localhost:9200&quot;]</span><br><span class="line">    index =&gt; &quot;xxx-logstash-%&#123;+YYYY.MM.dd&#125;&quot;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>kibana安装logtrail，logtrail对应版本地址请在 <a href="https://github.com/sivasamyk/logtrail" target="_blank" rel="noopener">https://github.com/sivasamyk/logtrail</a> 获取</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">kibana-plugin.bat install https://github.com/sivasamyk/logtrail/releases/download/v0.1.31/logtrail-7.6.2-0.1.31.zip</span><br></pre></td></tr></table></figure><p>logtrail.json配置</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  &quot;version&quot; : 2,</span><br><span class="line">  &quot;index_patterns&quot; : [</span><br><span class="line">    &#123;      </span><br><span class="line">      &quot;es&quot;: &#123;</span><br><span class="line">        &quot;default_index&quot;: &quot;xxx-logstash-*&quot;</span><br><span class="line">      &#125;,</span><br><span class="line">      &quot;tail_interval_in_seconds&quot;: 10,</span><br><span class="line">      &quot;es_index_time_offset_in_seconds&quot;: 0,</span><br><span class="line">      &quot;display_timezone&quot;: &quot;local&quot;,</span><br><span class="line">      &quot;display_timestamp_format&quot;: &quot;YYYY-MM-DD HH:mm:ss&quot;,</span><br><span class="line">      &quot;max_buckets&quot;: 500,</span><br><span class="line">      &quot;default_time_range_in_days&quot; : 0,</span><br><span class="line">      &quot;max_hosts&quot;: 100,</span><br><span class="line">      &quot;max_events_to_keep_in_viewer&quot;: 5000,</span><br><span class="line">      &quot;default_search&quot;: &quot;&quot;,</span><br><span class="line">      &quot;fields&quot; : &#123;</span><br><span class="line">        &quot;mapping&quot; : &#123;</span><br><span class="line">            &quot;timestamp&quot; : &quot;@timestamp&quot;,</span><br><span class="line">            &quot;hostname&quot; : &quot;host&quot;,</span><br><span class="line">            &quot;message&quot;: &quot;message&quot;</span><br><span class="line">            </span><br><span class="line">        &#125;,</span><br><span class="line">        &quot;message_format&quot;: &quot;&#123;&#123;&#123;tid&#125;&#125;&#125;|&#123;&#123;&#123;level&#125;&#125;&#125;|&#123;&#123;&#123;logger_name&#125;&#125;&#125;|&#123;&#123;&#123;message&#125;&#125;&#125;&quot;,</span><br><span class="line">        &quot;keyword_suffix&quot; : &quot;keyword&quot;</span><br><span class="line">      &#125;,</span><br><span class="line">      &quot;color_mapping&quot; : &#123;</span><br><span class="line">&quot;field&quot;: &quot;level&quot;,</span><br><span class="line">&quot;mapping&quot;: &#123;</span><br><span class="line">&quot;ERROR&quot;: &quot;#FF0000&quot;,</span><br><span class="line">&quot;WARN&quot;: &quot;#FFEF96&quot;,</span><br><span class="line">&quot;DEBUG&quot;: &quot;#B5E7A0&quot;,</span><br><span class="line">&quot;TRACE&quot;: &quot;#CFE0E8&quot;,</span><br><span class="line">&quot;INFO&quot;: &quot;#339999&quot;</span><br><span class="line">&#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;logstash与logback的集成，实现日志信息直接通过logstash发送到ES&lt;/p&gt;
    
    </summary>
    
      <category term="java" scheme="https://www.caozhg.com/categories/java/"/>
    
    
      <category term="ELK" scheme="https://www.caozhg.com/tags/ELK/"/>
    
      <category term="logback" scheme="https://www.caozhg.com/tags/logback/"/>
    
      <category term="springboot" scheme="https://www.caozhg.com/tags/springboot/"/>
    
      <category term="logstash" scheme="https://www.caozhg.com/tags/logstash/"/>
    
  </entry>
  
  <entry>
    <title>springboot 接口防刷</title>
    <link href="https://www.caozhg.com/2023/06/08/springboot-%E6%8E%A5%E5%8F%A3%E9%98%B2%E5%88%B7/"/>
    <id>https://www.caozhg.com/2023/06/08/springboot-接口防刷/</id>
    <published>2023-06-08T05:25:00.000Z</published>
    <updated>2023-06-08T05:28:39.994Z</updated>
    
    <content type="html"><![CDATA[<p>通过Interceptor以及Redis实现接口访问防刷</p><a id="more"></a><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 接口防刷</span><br><span class="line"> */</span><br><span class="line">@Slf4j</span><br><span class="line">public class AccessLimintInterceptor implements HandlerInterceptor &#123;</span><br><span class="line"></span><br><span class="line">    @Resource</span><br><span class="line">    private RedisTemplate&lt;String, Object&gt; redisTemplate;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 多长时间内</span><br><span class="line">     */</span><br><span class="line">    @Value(&quot;$&#123;interfaceAccess.second&#125;&quot;)</span><br><span class="line">    private final Long second = 10L;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 访问次数</span><br><span class="line">     */</span><br><span class="line">    @Value(&quot;$&#123;interfaceAccess.time&#125;&quot;)</span><br><span class="line">    private final Long time = 3L;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 禁用时长--单位/秒</span><br><span class="line">     */</span><br><span class="line">    @Value(&quot;$&#123;interfaceAccess.lockTime&#125;&quot;)</span><br><span class="line">    private final Long lockTime = 60L;</span><br><span class="line"></span><br><span class="line">    @Value(&quot;$&#123;interfaceAccess.methodUri&#125;&quot;)</span><br><span class="line">    private final String methodUri = &quot;&quot;;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 锁住时的key前缀</span><br><span class="line">     */</span><br><span class="line">    public static final String LOCK_PREFIX = &quot;METHOD_LOCK:&quot;;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 统计次数时的key前缀</span><br><span class="line">     */</span><br><span class="line">    public static final String COUNT_PREFIX = &quot;METHOD_LOCK_COUNT:&quot;;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception &#123;</span><br><span class="line"></span><br><span class="line">        String uri = request.getRequestURI();</span><br><span class="line">        String ip = request.getRemoteAddr(); // 这里忽略代理软件方式访问，默认直接访问，也就是获取得到的就是访问者真实ip地址</span><br><span class="line"></span><br><span class="line">        List&lt;String&gt; methodUriList = Arrays.asList(methodUri.split(&quot;,&quot;));</span><br><span class="line">        if (!methodUriList.contains(uri)) &#123;</span><br><span class="line">            return true;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        String lockKey = LOCK_PREFIX + ip + uri;</span><br><span class="line">        Object isLock = redisTemplate.opsForValue().get(lockKey);</span><br><span class="line">        if (Objects.isNull(isLock)) &#123;</span><br><span class="line">            // 还未被禁用</span><br><span class="line">            String countKey = COUNT_PREFIX + ip + uri;</span><br><span class="line">            Object count = redisTemplate.opsForValue().get(countKey);</span><br><span class="line">            if (Objects.isNull(count)) &#123;</span><br><span class="line">                // 首次访问</span><br><span class="line">                redisTemplate.opsForValue().set(countKey, 1, second, TimeUnit.SECONDS);</span><br><span class="line">            &#125; else &#123;</span><br><span class="line">                // 此用户前一点时间就访问过该接口</span><br><span class="line">                if ((Integer) count &lt; time) &#123;</span><br><span class="line">                    // 放行，访问次数 + 1</span><br><span class="line">                    redisTemplate.opsForValue().increment(countKey);</span><br><span class="line">                &#125; else &#123;</span><br><span class="line">                    log.info(&quot;&#123;&#125;禁用访问&#123;&#125;&quot;, ip, uri);</span><br><span class="line">                    // 禁用</span><br><span class="line">                    redisTemplate.opsForValue().set(lockKey, 1, lockTime, TimeUnit.SECONDS);</span><br><span class="line">                    // 删除统计</span><br><span class="line">                    redisTemplate.delete(countKey);</span><br><span class="line">                    throw new RuntimeException(&quot;访问过于频繁&quot;);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            // 此用户访问此接口已被禁用</span><br><span class="line">            throw new RuntimeException(&quot;访问过于频繁！&quot;);</span><br><span class="line">        &#125;</span><br><span class="line">        return true;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>application中添加</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 接口防刷配置，规定时间内，可以访问多少次</span><br><span class="line">interfaceAccess:</span><br><span class="line">  second: 60 # 时间，单位秒</span><br><span class="line">  time: 10 # 次数</span><br><span class="line">  lockTime: 60 #限制时长，单位秒</span><br><span class="line">  methodUri: /appointment/api/getDepts #限制的接口地址，使用英文逗号【,】分隔</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;通过Interceptor以及Redis实现接口访问防刷&lt;/p&gt;
    
    </summary>
    
      <category term="java" scheme="https://www.caozhg.com/categories/java/"/>
    
    
      <category term="springboot" scheme="https://www.caozhg.com/tags/springboot/"/>
    
  </entry>
  
  <entry>
    <title>windows 的 ping 脚本，记录日志</title>
    <link href="https://www.caozhg.com/2023/03/07/windows-%E7%9A%84-ping-%E8%84%9A%E6%9C%AC%EF%BC%8C%E8%AE%B0%E5%BD%95%E6%97%A5%E5%BF%97/"/>
    <id>https://www.caozhg.com/2023/03/07/windows-的-ping-脚本，记录日志/</id>
    <published>2023-03-07T06:00:00.000Z</published>
    <updated>2023-03-07T06:03:24.398Z</updated>
    
    <content type="html"><![CDATA[<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">@echo off</span><br><span class="line"></span><br><span class="line">set /p host=host:</span><br><span class="line"></span><br><span class="line">set logfile=%~dp0%host%.txt</span><br><span class="line">echo Target Host=%host% &gt; %logfile%</span><br><span class="line"></span><br><span class="line">:loop</span><br><span class="line">for /f &quot;tokens=* skip=2&quot; %%A in (&apos;ping %host% -n 1&apos;) do (</span><br><span class="line">  echo %date% %time:~0,-3% %%A&gt;&gt;%logfile%</span><br><span class="line">  echo %date% %time:~0,-3% %%A</span><br><span class="line">  timeout /t 1 /nobreak&gt;nul</span><br><span class="line">  goto loop</span><br><span class="line">)</span><br><span class="line">pause&gt;nul</span><br></pre></td></tr></table></figure><blockquote><p>如果输出乱码，请将 bat 编码改为 GBK</p></blockquote>]]></content>
    
    <summary type="html">
    
      
      
        &lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class
      
    
    </summary>
    
      <category term="windows" scheme="https://www.caozhg.com/categories/windows/"/>
    
    
      <category term="windows" scheme="https://www.caozhg.com/tags/windows/"/>
    
      <category term="bat" scheme="https://www.caozhg.com/tags/bat/"/>
    
      <category term="cmd" scheme="https://www.caozhg.com/tags/cmd/"/>
    
  </entry>
  
  <entry>
    <title>每天100w次登陆请求，8G内存该如何设置JVM参数</title>
    <link href="https://www.caozhg.com/2023/02/28/%E6%AF%8F%E5%A4%A9100w%E6%AC%A1%E7%99%BB%E9%99%86%E8%AF%B7%E6%B1%82%EF%BC%8C8G%E5%86%85%E5%AD%98%E8%AF%A5%E5%A6%82%E4%BD%95%E8%AE%BE%E7%BD%AEJVM%E5%8F%82%E6%95%B0/"/>
    <id>https://www.caozhg.com/2023/02/28/每天100w次登陆请求，8G内存该如何设置JVM参数/</id>
    <published>2023-02-28T02:36:00.000Z</published>
    <updated>2023-02-28T03:06:36.504Z</updated>
    
    <content type="html"><![CDATA[<h2 id="每天100w次登陆请求-8G-内存该如何设置JVM参数？"><a href="#每天100w次登陆请求-8G-内存该如何设置JVM参数？" class="headerlink" title="每天100w次登陆请求, 8G 内存该如何设置JVM参数？"></a>每天100w次登陆请求, 8G 内存该如何设置JVM参数？</h2><p>每天100w次登陆请求, 8G 内存该如何设置JVM参数，大概可以分为以下<strong>8个步骤</strong>。</p><h3 id="Step1：新系统上线如何规划容量？"><a href="#Step1：新系统上线如何规划容量？" class="headerlink" title="Step1：新系统上线如何规划容量？"></a>Step1：新系统上线如何规划容量？</h3><p><strong>1.套路总结</strong></p><p>任何新的业务系统在上线以前都需要去估算服务器配置和JVM的内存参数，这个容量与资源规划并不仅仅是系统架构师的随意估算的，需要根据系统所在业务场景去估算，推断出来一个系统运行模型，评估JVM性能和GC频率等等指标。以下是我结合大牛经验以及自身实践来总结出来的一个建模步骤：</p><ul><li>计算业务系统每秒钟创建的对象会佔用多大的内存空间，然后计算集群下的每个系统每秒的内存佔用空间（对象创建速度）</li><li>设置一个机器配置，估算新生代的空间，比较不同新生代大小之下，多久触发一次MinorGC。</li><li>为了避免频繁GC，就可以重新估算需要多少机器配置，部署多少台机器，给JVM多大内存空间，新生代多大空间。</li><li>根据这套配置，基本可以推算出整个系统的运行模型，每秒创建多少对象，1s以后成为垃圾，系统运行多久新生代会触发一次GC，频率多高。</li></ul><p><strong>2.套路实战——以登录系统为例</strong></p><p>有些同学看到这些步骤还是发憷，说的好像是那么回事，一到实际项目中到底怎麽做我还是不知道！</p><p>光说不练假把式，以登录系统为例模拟一下推演过程：</p><ul><li>假设每天100w次登陆请求，登陆峰值在早上，预估峰值时期每秒100次登陆请求。</li><li>假设部署3台服务器，每台机器每秒处理30次登陆请求，假设一个登陆请求需要处理1秒钟，JVM新生代里每秒就要生成30个登陆对象，1s之后请求完毕这些对象成为了垃圾。</li><li>一个登陆请求对象假设20个字段，一个对象估算500字节，30个登陆佔用大约15kb，考虑到RPC和DB操作，网络通信、写库、写缓存一顿操作下来，可以扩大到20-50倍，大约1s产生几百k-1M数据。</li><li>假设2C4G机器部署，分配2G堆内存，新生代则只有几百M，按照1s1M的垃圾产生速度，几百秒就会触发一次MinorGC了。</li><li>假设4C8G机器部署，分配4G堆内存，新生代分配2G，如此需要几个小时才会触发一次MinorGC。</li></ul><p>所以，可以粗略的推断出来一个每天100w次请求的登录系统，按照4C8G的3实例集群配置，分配4G堆内存、2G新生代的JVM，可以保障系统的一个正常负载。</p><p>基本上把一个新系统的资源评估了出来，所以搭建新系统要每个实例需要多少容量多少配置，集群配置多少个实例等等这些，并不是拍拍脑袋和胸脯就可以决定的下来的。</p><h3 id="Step2：该如何进行垃圾回收器的选择？"><a href="#Step2：该如何进行垃圾回收器的选择？" class="headerlink" title="Step2：该如何进行垃圾回收器的选择？"></a>Step2：该如何进行垃圾回收器的选择？</h3><h4 id="吞吐量还是响应时间"><a href="#吞吐量还是响应时间" class="headerlink" title="吞吐量还是响应时间"></a>吞吐量还是响应时间</h4><p>首先引入两个概念：吞吐量和低延迟</p><p>吞吐量 = CPU在用户应用程序运行的时间 / （CPU在用户应用程序运行的时间 + CPU垃圾回收的时间）</p><p>响应时间 = 平均每次的GC的耗时</p><p>通常，吞吐优先还是响应优先这个在JVM中是一个两难之选。</p><p>堆内存增大，gc一次能处理的数量变大，吞吐量大；但是gc一次的时间会变长，导致后面排队的线程等待时间变长；相反，如果堆内存小，gc一次时间短，排队等待的线程等待时间变短，延迟减少，但一次请求的数量变小（并不绝对符合）。</p><p>无法同时兼顾，是吞吐优先还是响应优先，这是一个需要权衡的问题。</p><h4 id="垃圾回收器设计上的考量"><a href="#垃圾回收器设计上的考量" class="headerlink" title="垃圾回收器设计上的考量"></a>垃圾回收器设计上的考量</h4><ul><li>JVM在GC时不允许一边垃圾回收，一边还创建新对象（就像不能一边打扫卫生，还在一边扔垃圾）。</li><li>JVM需要一段Stop the world的暂停时间，而STW会造成系统短暂停顿不能处理任何请求；</li><li>新生代收集频率高，性能优先，常用复制算法；老年代频次低，空间敏感，避免复制方式。</li><li>所有垃圾回收器的涉及目标都是要让GC频率更少，时间更短，减少GC对系统影响！</li></ul><h4 id="CMS和G1"><a href="#CMS和G1" class="headerlink" title="CMS和G1"></a>CMS和G1</h4><p>目前主流的垃圾回收器配置是新生代采用ParNew，老年代采用CMS组合的方式，或者是完全采用G1回收器，</p><p>从未来的趋势来看，G1是官方维护和更为推崇的垃圾回收器。</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/jvm/1.webp" alt title>                </div>                <div class="image-caption"></div>            </figure><p>业务系统:</p><ul><li>延迟敏感的推荐CMS；</li><li>大内存服务，要求高吞吐的，采用G1回收器！</li></ul><h4 id="CMS垃圾回收器的工作机制"><a href="#CMS垃圾回收器的工作机制" class="headerlink" title="CMS垃圾回收器的工作机制"></a>CMS垃圾回收器的工作机制</h4><p>CMS主要是针对老年代的回收器，老年代是标记-清除，默认会在一次FullGC算法后做整理算法，清理内存碎片。</p><table><thead><tr><th>CMS GC</th><th>描述</th><th>Stop the world</th><th>速度</th></tr></thead><tbody><tr><td>1.开始标记</td><td>初始标记仅标记GCRoots能直接关联到的对象，速度很快</td><td>Yes</td><td>很快</td></tr><tr><td>2.并发标记</td><td>并发标记阶段就是进行GCRoots Tracing的过程</td><td>No</td><td>慢</td></tr><tr><td>3.重新标记</td><td>重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录。</td><td>Yes</td><td>很快</td></tr><tr><td>4.垃圾回收</td><td>并发清理垃圾对象(标记清除算法)</td><td>No</td><td>慢</td></tr></tbody></table><ul><li>优点：并发收集、主打“低延时” 。在最耗时的两个阶段都没有发生STW，而需要STW的阶段都以很快速度完成。</li><li>缺点：1、消耗CPU；2、浮动垃圾；3、内存碎片</li><li>适用场景：重视服务器响应速度，要求系统停顿时间最短。</li></ul><p><strong>总之：</strong></p><p><strong>业务系统，延迟敏感的推荐CMS；</strong></p><p><strong>大内存服务，要求高吞吐的，采用G1回收器！</strong></p><h3 id="Step3：如何对各个分区的比例、大小进行规划"><a href="#Step3：如何对各个分区的比例、大小进行规划" class="headerlink" title="Step3：如何对各个分区的比例、大小进行规划"></a>Step3：如何对各个分区的比例、大小进行规划</h3><p>一般的思路为:</p><p>首先，JVM最重要最核心的参数是去评估内存和分配，第一步需要指定堆内存的大小，这个是系统上线必须要做的，-Xms 初始堆大小，-Xmx 最大堆大小，后台Java服务中一般都指定为系统内存的一半，过大会佔用服务器的系统资源，过小则无法发挥JVM的最佳性能。</p><p>其次，需要指定-Xmn新生代的大小，这个参数非常关键，灵活度很大，虽然sun官方推荐为3/8大小，但是要根据业务场景来定，针对于无状态或者轻状态服务（现在最常见的业务系统如Web应用）来说，一般新生代甚至可以给到堆内存的3/4大小；而对于有状态服务（常见如IM服务、网关接入层等系统）新生代可以按照默认比例1/3来设置。服务有状态，则意味著会有更多的本地缓存和会话状态信息常驻内存，应为要给老年代设置更大的空间来存放这些对象。</p><p>最后，是设置-Xss栈内存大小，设置单个线程栈大小，默认值和JDK版本、系统有关，一般默认512~1024kb。一个后台服务如果常驻线程有几百个，那麽栈内存这边也会佔用了几百M的大小。</p><p>|JVM参数|描述|默认|推荐|<br>|-Xms|Java堆内存的大小|OS内存64/1|OS内存一半|<br>|-Xmx|Java堆内存的最大大小|OS内存4/1|OS内存一半|<br>|-Xmn|Java堆内存中的新生代大小，扣除新生代剩下的就是老年代的内存大小了|跌认堆的1/3|sun推荐3/8|<br>|-Xss|每个线程的栈内存大小|和idk有关|sun|</p><p>对于8G内存，一般分配一半的最大内存就可以了,因为机器本上还要占用一定内存，一般是分配4G内存给JVM，</p><p>引入性能压测环节，测试同学对登录接口压至1s内60M的对象生成速度，采用ParNew+CMS的组合回收器，</p><p>正常的JVM参数配置如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-Xms3072M -Xmx3072M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:SurvivorRatio=8</span><br></pre></td></tr></table></figure><p>这样设置可能会由于<strong>动态对象年龄判断原则</strong>导致频繁full gc。为啥呢？</p><p>压测过程中，短时间（比如20S后）Eden区就满了，此时再运行的时候对象已经无法分配，会触发MinorGC，</p><p>假设在这次GC后S1装入100M，马上过20S又会触发一次MinorGC，多出来的100M存活对象+S1区的100M已经无法顺利放入到S2区，此时就会触发JVM的动态年龄机制，将一批100M左右的对象推到老年代保存，持续运行一段时间，系统可能一个小时候内就会触发一次FullGC。</p><p>按照默认8:1:1的比例来分配时, survivor区只有 1G的 10%左右，也就是几十到100M，</p><p>如果 每次minor GC垃圾回收过后进入survivor对象很多，并且survivor对象大小很快超过 Survivor 的 50% ， 那么会触发动态年龄判定规则，让部分对象进入老年代.</p><p>而一个GC过程中，可能部分WEB请求未处理完毕, 几十兆对象，进入survivor的概率，是非常大的，甚至是一定会发生的.</p><p><strong>如何解决这个问题呢？ 为了让对象尽可能的在新生代的eden区和survivor区, 尽可能的让survivor区内存多一点,达到200兆左右,</strong></p><p>于是我们可以更新下JVM参数设置：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">-Xms3072M -Xmx3072M -Xmn2048M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M  -XX:SurvivorRatio=8  </span><br><span class="line">    </span><br><span class="line">说明：</span><br><span class="line">-Xmn2048M -XX:SurvivorRatio=8 </span><br><span class="line">年轻代大小2g，eden与survivor的比例为8:1:1，也就是1.6g:0.2g:0.2g</span><br></pre></td></tr></table></figure><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/jvm/2.webp" alt title>                </div>                <div class="image-caption"></div>            </figure><p>survivor达到200m，如果几十兆对象到底survivor， survivor 也不一定超过 50%</p><p>这样可以防止每次垃圾回收过后，survivor对象太早超过 50% ,</p><p>这样就降低了因为对象动态年龄判断原则导致的对象频繁进入老年代的问题，</p><h4 id="什么是JVM动态年龄判断规则呢？"><a href="#什么是JVM动态年龄判断规则呢？" class="headerlink" title="什么是JVM动态年龄判断规则呢？"></a>什么是JVM动态年龄判断规则呢？</h4><p>对象进入老年代的<strong>动态年龄判断规则</strong>（动态晋升年龄计算阈值）：Minor GC 时，Survivor 中年龄 1 到 N 的对象大小超过 Survivor 的 50% 时，则将大于等于年龄 N 的对象放入老年代。</p><p><strong>核心的优化策略是：是让短期存活的对象尽量都留在survivor里，不要进入老年代，这样在minor gc的时候这些对象都会被回收，不会进到老年代从而导致full gc</strong>。</p><h4 id="应该如何去评估新生代内存和分配合适？"><a href="#应该如何去评估新生代内存和分配合适？" class="headerlink" title="应该如何去评估新生代内存和分配合适？"></a>应该如何去评估新生代内存和分配合适？</h4><p>这里特别说一下，JVM最重要最核心的参数是去评估内存和分配，</p><p>第一步需要指定堆内存的大小，这个是系统上线必须要做的，-Xms 初始堆大小，-Xmx 最大堆大小，</p><p>后台Java服务中一般都指定为系统内存的一半，过大会佔用服务器的系统资源，过小则无法发挥JVM的最佳性能。</p><p>其次需要指定-Xmn新生代的大小，这个参数非常关键，灵活度很大，虽然sun官方推荐为3/8大小，但是要根据业务场景来定：</p><ul><li>针对于无状态或者轻状态服务（现在最常见的业务系统如Web应用）来说，一般新生代甚至可以给到堆内存的3/4大小；</li><li>而对于有状态服务（常见如IM服务、网关接入层等系统）新生代可以按照默认比例1/3来设置。</li></ul><p>服务有状态，则意味著会有更多的本地缓存和会话状态信息常驻内存，应为要给老年代设置更大的空间来存放这些对象。</p><h3 id="step4：栈内存大小多少比较合适？"><a href="#step4：栈内存大小多少比较合适？" class="headerlink" title="step4：栈内存大小多少比较合适？"></a>step4：栈内存大小多少比较合适？</h3><p>-Xss栈内存大小，设置单个线程栈大小，默认值和JDK版本、系统有关，一般默认512~1024kb。一个后台服务如果常驻线程有几百个，那麽栈内存这边也会佔用了几百M的大小。</p><h3 id="step5：对象年龄应该为多少才移动到老年代比较合适？"><a href="#step5：对象年龄应该为多少才移动到老年代比较合适？" class="headerlink" title="step5：对象年龄应该为多少才移动到老年代比较合适？"></a>step5：对象年龄应该为多少才移动到老年代比较合适？</h3><p>假设一次minor gc要间隔二三十秒，并且，大多数对象一般在几秒内就会变为垃圾，</p><p>如果对象这么长时间都没被回收，比如2分钟没有回收，可以认为这些对象是会存活的比较长的对象，从而移动到老年代，而不是继续一直占用survivor区空间。</p><p>所以，可以将默认的15岁改小一点，比如改为5，</p><p>那么意味着对象要经过5次minor gc才会进入老年代，整个时间也有一两分钟了（5*30s= 150s），和几秒的时间相比，对象已经存活了足够长时间了。</p><p>所以：可以适当调整JVM参数如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-Xms3072M -Xmx3072M -Xmn2048M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=5</span><br></pre></td></tr></table></figure><h3 id="step6：多大的对象，可以直接到老年代比较合适？"><a href="#step6：多大的对象，可以直接到老年代比较合适？" class="headerlink" title="step6：多大的对象，可以直接到老年代比较合适？"></a>step6：多大的对象，可以直接到老年代比较合适？</h3><p>对于多大的对象直接进入老年代(参数-XX:PretenureSizeThreshold)，一般可以结合自己系统看下有没有什么大对象 生成，预估下大对象的大小，一般来说设置为1M就差不多了，很少有超过1M的大对象，</p><p>所以：可以适当调整JVM参数如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-Xms3072M -Xmx3072M -Xmn2048M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=5 -XX:PretenureSizeThreshold=1M</span><br></pre></td></tr></table></figure><h3 id="step7：垃圾回收器CMS老年代的参数优化"><a href="#step7：垃圾回收器CMS老年代的参数优化" class="headerlink" title="step7：垃圾回收器CMS老年代的参数优化"></a>step7：垃圾回收器CMS老年代的参数优化</h3><p>JDK8默认的垃圾回收器是-XX:+UseParallelGC(年轻代)和-XX:+UseParallelOldGC(老年代)，</p><p>如果内存较大(超过4个G，只是经验 值)，还是建议使用G1.</p><p>这里是4G以内，又是主打“低延时” 的业务系统，可以使用下面的组合：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ParNew+CMS(-XX:+UseParNewGC -XX:+UseConcMarkSweepGC)</span><br></pre></td></tr></table></figure><p>新生代的采用ParNew回收器，工作流程就是经典复制算法，在三块区中进行流转回收，只不过采用多线程并行的方式加快了MinorGC速度。</p><p>老生代的采用CMS。再去<strong>优化老年代参数</strong>：比如老年代默认在标记清除以后会做整理，还可以在CMS的增加GC频次还是增加GC时长上做些取舍，</p><p>如下是响应优先的参数调优：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">XX:CMSInitiatingOccupancyFraction=70</span><br></pre></td></tr></table></figure><p>设定CMS在对内存占用率达到70%的时候开始GC(因为CMS会有浮动垃圾,所以一般都较早启动GC)</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">XX:+UseCMSInitiatinpOccupancyOnly</span><br></pre></td></tr></table></figure><p>和上面搭配使用，否则只生效一次</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-XX:+AlwaysPreTouch</span><br></pre></td></tr></table></figure><p>强制操作系统把内存真正分配给IVM，而不是用时才分配。</p><p>综上，只要年轻代参数设置合理，老年代CMS的参数设置基本都可以用默认值，如下所示：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-Xms3072M -Xmx3072M -Xmn2048M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:SurvivorRatio=8  -XX:MaxTenuringThreshold=5 -XX:PretenureSizeThreshold=1M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly -XX:+AlwaysPreTouch</span><br></pre></td></tr></table></figure><p><strong>参数解释</strong></p><p>1.<code>-Xms3072M -Xmx3072M</code> 最小最大堆设置为3g，最大最小设置为一致防止内存抖动</p><p>2.<code>-Xss1M</code> 线程栈1m</p><p>3.<code>-Xmn2048M -XX:SurvivorRatio=8</code> 年轻代大小2g，eden与survivor的比例为8:1:1，也就是1.6g:0.2g:0.2g</p><p>4.<code>-XX:MaxTenuringThreshold=5</code> 年龄为5进入老年代 5.-<code>XX:PretenureSizeThreshold=1M</code> 大于1m的大对象直接在老年代生成</p><p>6.<code>-XX:+UseParNewGC -XX:+UseConcMarkSweepGC</code> 使用ParNew+cms垃圾回收器组合</p><p>7.<code>-XX:CMSInitiatingOccupancyFraction=70</code> 老年代中对象达到这个比例后触发fullgc</p><p>8.<code>-XX:+UseCMSInitiatinpOccupancyOnly</code> 老年代中对象达到这个比例后触发fullgc，每次</p><p>9.<code>-XX:+AlwaysPreTouch</code> 强制操作系统把内存真正分配给IVM，而不是用时才分配。</p><h3 id="step8：配置OOM时候的内存dump文件和GC日志"><a href="#step8：配置OOM时候的内存dump文件和GC日志" class="headerlink" title="step8：配置OOM时候的内存dump文件和GC日志"></a>step8：配置OOM时候的内存dump文件和GC日志</h3><p>额外增加了GC日志打印、OOM自动dump等配置内容，帮助进行问题排查</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-XX:+HeapDumpOnOutOfMemoryError</span><br></pre></td></tr></table></figure><p>在Out Of Memory，JVM快死掉的时候，输出Heap Dump到指定文件。</p><p>不然开发很多时候还真不知道怎么重现错误。</p><p>路径只指向目录，JVM会保持文件名的唯一性，叫java_pid${pid}.hprof。</p><figure class="highlight plain"><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">-XX:+HeapDumpOnOutOfMemoryError </span><br><span class="line">-XX:HeapDumpPath=$&#123;LOGDIR&#125;/</span><br></pre></td></tr></table></figure><p>因为如果指向特定的文件，而文件已存在，反而不能写入。</p><p>输出4G的HeapDump，会导致IO性能问题，在普通硬盘上，会造成20秒以上的硬盘IO跑满，</p><p>需要注意一下，但在容器环境下，这个也会影响同一宿主机上的其他容器。</p><p>GC的日志的输出也很重要：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">-Xloggc:/dev/xxx/gc.log </span><br><span class="line">-XX:+PrintGCDateStamps </span><br><span class="line">-XX:+PrintGCDetails</span><br></pre></td></tr></table></figure><p>GC的日志实际上对系统性能影响不大，打日志对排查GC问题很重要。</p><h4 id="一份通用的JVM参数模板"><a href="#一份通用的JVM参数模板" class="headerlink" title="一份通用的JVM参数模板"></a>一份通用的JVM参数模板</h4><blockquote><p>一般来说，大企业或者架构师团队，都会为项目的业务系统定制一份较为通用的JVM参数模板，但是许多小企业和团队可能就疏于这一块的设计，如果老板某一天突然让你负责定制一个新系统的JVM参数，你上网去搜大量的JVM调优文章或博客，结果发现都是零零散散的、不成体系的JVM参数讲解，根本下不了手，这个时候你就需要一份较为通用的JVM参数模板了，不能保证性能最佳，但是至少能让JVM这一层是稳定可控的，</p><p>在这里给大家总结了一份模板：</p></blockquote><p><strong>基于4C8G系统的ParNew+CMS回收器模板（响应优先），新生代大小根据业务灵活调整！</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">-Xms4g</span><br><span class="line">-Xmx4g</span><br><span class="line">-Xmn2g</span><br><span class="line">-Xss1m</span><br><span class="line">-XX:SurvivorRatio=8</span><br><span class="line">-XX:MaxTenuringThreshold=10</span><br><span class="line">-XX:+UseConcMarkSweepGC</span><br><span class="line">-XX:CMSInitiatingOccupancyFraction=70</span><br><span class="line">-XX:+UseCMSInitiatingOccupancyOnly</span><br><span class="line">-XX:+AlwaysPreTouch</span><br><span class="line">-XX:+HeapDumpOnOutOfMemoryError</span><br><span class="line">-verbose:gc</span><br><span class="line">-XX:+PrintGCDetails</span><br><span class="line">-XX:+PrintGCDateStamps</span><br><span class="line">-XX:+PrintGCTimeStamps</span><br><span class="line">-Xloggc:gc.log</span><br></pre></td></tr></table></figure><h4 id="如果是GC的吞吐优先，推荐使用G1，基于8C16G系统的G1回收器模板："><a href="#如果是GC的吞吐优先，推荐使用G1，基于8C16G系统的G1回收器模板：" class="headerlink" title="如果是GC的吞吐优先，推荐使用G1，基于8C16G系统的G1回收器模板："></a>如果是GC的吞吐优先，推荐使用G1，基于8C16G系统的G1回收器模板：</h4><p>G1收集器自身已经有一套预测和调整机制了，因此我们首先的选择是相信它，</p><p>即调整-<code>XX:MaxGCPauseMillis=N</code>参数，这也符合G1的目的——让GC调优尽量简单！</p><p>同时也不要自己显式设置新生代的大小（用-Xmn或-XX:NewRatio参数），</p><p>如果人为干预新生代的大小，会导致目标时间这个参数失效。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">-Xms8g</span><br><span class="line">-Xmx8g</span><br><span class="line">-Xss1m</span><br><span class="line">-XX:+UseG1GC</span><br><span class="line">-XX:MaxGCPauseMillis=150</span><br><span class="line">-XX:InitiatingHeapOccupancyPercent=40</span><br><span class="line">-XX:+HeapDumpOnOutOfMemoryError</span><br><span class="line">-verbose:gc</span><br><span class="line">-XX:+PrintGCDetails</span><br><span class="line">-XX:+PrintGCDateStamps</span><br><span class="line">-XX:+PrintGCTimeStamps</span><br><span class="line">-Xloggc:gc.log</span><br></pre></td></tr></table></figure><table><thead><tr><th>G1参数</th><th>描述</th><th>默认值</th></tr></thead><tbody><tr><td>XX:MaxGCPauseMillis=N</td><td>最大GC停顿时间。柔性目标，JVM满足90%，不保证100%。</td><td>200</td></tr><tr><td>-XX:nitiatingHeapOccupancyPercent=n</td><td>当整个堆的空间使用百分比超过这个值时，就会融发MixGC</td><td>45</td></tr></tbody></table><p>针对<code>-XX:MaxGCPauseMillis</code>来说，参数的设置带有明显的倾向性：调低↓：延迟更低，但MinorGC频繁，MixGC回收老年代区减少，增大Full GC的风险。调高↑：单次回收更多的对象，但系统整体响应时间也会被拉长。</p><p>针对<code>InitiatingHeapOccupancyPercent</code>来说，调参大小的效果也不一样：调低↓：更早触发MixGC，浪费cpu。调高↑：堆积过多代回收region，增大FullGC的风险。</p><h3 id="调优总结"><a href="#调优总结" class="headerlink" title="调优总结"></a>调优总结</h3><p>系统在上线前的综合调优思路：</p><p>1、业务预估：根据预期的并发量、平均每个任务的内存需求大小，然后评估需要几台机器来承载，每台机器需要什么样的配置。</p><p>2、容量预估：根据系统的任务处理速度，然后合理分配Eden、Surivior区大小，老年代的内存大小。</p><p>3、回收器选型：响应优先的系统，建议采用ParNew+CMS回收器；吞吐优先、多核大内存(heap size≥8G)服务，建议采用G1回收器。</p><p>4、优化思路：让短命对象在MinorGC阶段就被回收（同时回收后的存活对象&lt;Survivor区域50%，可控制保留在新生代），长命对象尽早进入老年代，不要在新生代来回复制；尽量减少Full GC的频率，避免FGC系统的影响。</p><p>5、到目前为止，总结到的调优的过程主要基于上线前的测试验证阶段，所以我们尽量在上线之前，就将机器的JVM参数设置到最优！</p><p>JVM调优只是一个手段，但并不一定所有问题都可以通过JVM进行调优解决，大多数的Java应用不需要进行JVM优化，我们可以遵循以下的一些原则：</p><ul><li>上线之前，应先考虑将机器的JVM参数设置到最优；</li><li>减少创建对象的数量（代码层面）；</li><li>减少使用全局变量和大对象（代码层面）；</li><li>优先架构调优和代码调优，JVM优化是不得已的手段（代码、架构层面）；</li><li>分析GC情况优化代码比优化JVM参数更好（代码层面）；</li></ul><p>通过以上原则，我们发现，其实最有效的优化手段是架构和代码层面的优化，而JVM优化则是最后不得已的手段，也可以说是对服务器配置的最后一次“压榨”。</p><h2 id="什么是ZGC？"><a href="#什么是ZGC？" class="headerlink" title="什么是ZGC？"></a>什么是ZGC？</h2><p>ZGC （Z Garbage Collector）是一款由Oracle公司研发的，以低延迟为首要目标的一款垃圾收集器。</p><p>它是基于动态Region内存布局，（暂时）不设年龄分代，使用了读屏障、染色指针和内存多重映射等技术来实现可并发的标记-整理算法的收集器。</p><p>在 JDK 11 新加入，还在实验阶段，</p><p>主要特点是：回收TB级内存（最大4T），停顿时间不超过10ms。</p><p>优点：低停顿，高吞吐量， ZGC 收集过程中额外耗费的内存小</p><p>缺点：浮动垃圾</p><p>目前使用的非常少，真正普及还是需要写时间的。</p><h2 id="如何选择垃圾收集器？"><a href="#如何选择垃圾收集器？" class="headerlink" title="如何选择垃圾收集器？"></a>如何选择垃圾收集器？</h2><p>在真实场景中应该如何去选择呢，下面给出几种建议，希望对你有帮助：</p><p>1、如果你的堆大小不是很大（比如 100MB ），选择串行收集器一般是效率最高的。参数：<code>-XX:+UseSerialGC</code> 。</p><p>2、如果你的应用运行在单核的机器上，或者你的虚拟机核数只有 单核，选择串行收集器依然是合适的，这时候启用一些并行收集器没有任何收益。参数：<code>-XX:+UseSerialGC</code> 。</p><p>3、如果你的应用是“吞吐量”优先的，并且对较长时间的停顿没有什么特别的要求。选择并行收集器是比较好的。参数：<code>-XX:+UseParallelGC</code> 。</p><p>4、如果你的应用对响应时间要求较高，想要较少的停顿。甚至 1 秒的停顿都会引起大量的请求失败，那么选择 G1 、 ZGC 、 CMS 都是合理的。虽然这些收集器的 GC 停顿通常都比较短，但它需要一些额外的资源去处理这些工作，通常吞吐量会低一些。参数：<code>-XX:+UseConcMarkSweepGC</code> 、 <code>-XX:+UseG1GC</code> 、 <code>-XX:+UseZGC</code> 等。从上面这些出发点来看，我们平常的 Web 服务器，都是对响应性要求非常高的。</p><p>选择性其实就集中在 CMS、G1、ZGC 上。而对于某些定时任务，使用并行收集器，是一个比较好的选择。</p><h2 id="Hotspot为什么使用元空间替换了永久代？"><a href="#Hotspot为什么使用元空间替换了永久代？" class="headerlink" title="Hotspot为什么使用元空间替换了永久代？"></a>Hotspot为什么使用元空间替换了永久代？</h2><p><strong>什么是元空间？什么是永久代？为什么用元空间代替永久代？</strong></p><p>我们先回顾一下<strong>方法区</strong>吧,看看虚拟机运行时数据内存图，如下:</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/jvm/3.webp" alt title>                </div>                <div class="image-caption"></div>            </figure><p>方法区和堆一样，是各个线程共享的内存区域，它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。</p><p><strong>什么是永久代？它和方法区有什么关系呢？</strong></p><p>如果在HotSpot虚拟机上开发、部署，很多程序员都把方法区称作永久代。</p><p>可以说方法区是规范，永久代是Hotspot针对该规范进行的实现。</p><p>在Java7及以前的版本，方法区都是永久代实现的。</p><p><strong>什么是元空间？它和方法区有什么关系呢？</strong></p><p>对于Java8，HotSpots取消了永久代，取而代之的是元空间(Metaspace)。</p><p>换句话说，就是方法区还是在的，只是实现变了，从永久代变为元空间了。</p><p><strong>为什么使用元空间替换了永久代？</strong></p><p>永久代的方法区，和堆使用的物理内存是连续的。</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/jvm/4.webp" alt title>                </div>                <div class="image-caption"></div>            </figure><p><strong>永久代</strong>是通过以下这两个参数配置大小的~</p><ul><li><code>-XX:PremSize</code>：设置永久代的初始大小</li><li><code>-XX:MaxPermSize</code>: 设置永久代的最大值，默认是64M</li></ul><p>对于<strong>永久代</strong>，如果动态生成很多class的话，就很可能出现<strong>java.lang.OutOfMemoryError:PermGen space错误</strong>，因为永久代空间配置有限嘛。最典型的场景是，在web开发比较多jsp页面的时候。</p><p>JDK8之后，方法区存在于元空间(Metaspace)。</p><p>物理内存不再与堆连续，而是直接存在于本地内存中，理论上机器<strong>内存有多大，元空间就有多大</strong>。</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/jvm/5.webp" alt title>                </div>                <div class="image-caption"></div>            </figure><p>可以通过以下的参数来设置元空间的大小：</p><ul><li><code>-XX:MetaspaceSize</code>，初始空间大小，达到该值就会触发垃圾收集进行类型卸载，同时GC会对该值进行调整：如果释放了大量的空间，就适当降低该值；如果释放了很少的空间，那么在不超过MaxMetaspaceSize时，适当提高该值。</li><li><code>-XX:MaxMetaspaceSize</code>，最大空间，默认是没有限制的。</li><li><code>-XX:MinMetaspaceFreeRatio</code>，在GC之后，最小的Metaspace剩余空间容量的百分比，减少为分配空间所导致的垃圾收集</li><li><code>-XX:MaxMetaspaceFreeRatio</code>，在GC之后，最大的Metaspace剩余空间容量的百分比，减少为释放空间所导致的垃圾收集</li></ul><p>所以，为什么使用元空间替换永久代？</p><p>表面上看是为了避免OOM异常。</p><p>因为通常使用PermSize和MaxPermSize设置永久代的大小就决定了永久代的上限，但是不是总能知道应该设置为多大合适, 如果使用默认值很容易遇到OOM错误。</p><p>当使用元空间时，可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统的实际可用空间来控制啦。</p><h2 id="什么是Stop-The-World-什么是OopMap？什么是安全点？"><a href="#什么是Stop-The-World-什么是OopMap？什么是安全点？" class="headerlink" title="什么是Stop The World ? 什么是OopMap？什么是安全点？"></a>什么是Stop The World ? 什么是OopMap？什么是安全点？</h2><p>进行垃圾回收的过程中，会涉及对象的移动。</p><p>为了保证对象引用更新的正确性，必须暂停所有的用户线程，像这样的停顿，虚拟机设计者形象描述为<strong>Stop The World</strong>。也简称为STW。</p><p>在HotSpot中，有个数据结构（映射表）称为<strong>OopMap</strong>。</p><p>一旦类加载动作完成的时候，HotSpot就会把对象内什么偏移量上是什么类型的数据计算出来，记录到OopMap。</p><p>在即时编译过程中，也会在<strong>特定的位置</strong>生成 OopMap，记录下栈上和寄存器里哪些位置是引用。</p><p>这些特定的位置主要在：1.循环的末尾（非 counted 循环）</p><p>2.方法临返回前 / 调用方法的call指令后</p><p>3.可能抛异常的位置</p><p>这些位置就叫作<strong>安全点(safepoint)。</strong></p><p>用户程序执行时并非在代码指令流的任意位置都能够在停顿下来开始垃圾收集，而是必须是执行到安全点才能够暂停。</p><blockquote><p>—— 文章转自 <a href="https://juejin.cn/post/7203255955214172218?#heading-0" target="_blank" rel="noopener">https://juejin.cn/post/7203255955214172218?#heading-0</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;每天100w次登陆请求-8G-内存该如何设置JVM参数？&quot;&gt;&lt;a href=&quot;#每天100w次登陆请求-8G-内存该如何设置JVM参数？&quot; class=&quot;headerlink&quot; title=&quot;每天100w次登陆请求, 8G 内存该如何设置JVM参数？&quot;&gt;&lt;/a&gt;每
      
    
    </summary>
    
      <category term="java" scheme="https://www.caozhg.com/categories/java/"/>
    
    
      <category term="java" scheme="https://www.caozhg.com/tags/java/"/>
    
      <category term="jvm" scheme="https://www.caozhg.com/tags/jvm/"/>
    
  </entry>
  
  <entry>
    <title>Maven 生命周期和插件</title>
    <link href="https://www.caozhg.com/2023/02/22/Maven-%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%92%8C%E6%8F%92%E4%BB%B6/"/>
    <id>https://www.caozhg.com/2023/02/22/Maven-生命周期和插件/</id>
    <published>2023-02-22T06:24:00.000Z</published>
    <updated>2023-02-22T08:39:00.402Z</updated>
    
    <content type="html"><![CDATA[<h1 id="用户属性Properties的使用"><a href="#用户属性Properties的使用" class="headerlink" title="用户属性Properties的使用"></a>用户属性Properties的使用</h1><p>项目pom.xml中，有下面这样一段依赖：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependencies&gt;</span><br><span class="line">    &lt;dependency&gt;</span><br><span class="line">        &lt;groupId&gt;org.springframework&lt;/groupId&gt;</span><br><span class="line">        &lt;artifactId&gt;spring-core&lt;/artifactId&gt;</span><br><span class="line">        &lt;version&gt;5.2.1.RELEASE&lt;/version&gt;</span><br><span class="line">    &lt;/dependency&gt;</span><br><span class="line">    &lt;dependency&gt;</span><br><span class="line">        &lt;groupId&gt;org.springframework&lt;/groupId&gt;</span><br><span class="line">        &lt;artifactId&gt;spring-beans&lt;/artifactId&gt;</span><br><span class="line">        &lt;version&gt;5.2.1.RELEASE&lt;/version&gt;</span><br><span class="line">    &lt;/dependency&gt;</span><br><span class="line">    &lt;dependency&gt;</span><br><span class="line">        &lt;groupId&gt;org.springframework&lt;/groupId&gt;</span><br><span class="line">        &lt;artifactId&gt;spring-aop&lt;/artifactId&gt;</span><br><span class="line">        &lt;version&gt;5.2.1.RELEASE&lt;/version&gt;</span><br><span class="line">    &lt;/dependency&gt;</span><br><span class="line">&lt;/dependencies&gt;</span><br></pre></td></tr></table></figure><p>上面的配置，有没有什么问题？</p><p>他们的groupId和version都是一样的，程序员面对与重复的代码，需要提取，如果是java代码中，我们可以将同样的代码或者变量值，提取成方法或者变量，做到重用，方便维护。</p><p>那么maven的pom.xml中也支持这么做：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&lt;properties&gt;</span><br><span class="line">    &lt;spring.group&gt;org.springframework&lt;/spring.group&gt;</span><br><span class="line">    &lt;spring.version&gt;5.2.1.RELEASE&lt;/spring.version&gt;</span><br><span class="line">&lt;/properties&gt;</span><br><span class="line"> </span><br><span class="line">&lt;dependencies&gt;</span><br><span class="line">    &lt;dependency&gt;</span><br><span class="line">        &lt;groupId&gt;$&#123;spring.group&#125;&lt;/groupId&gt;</span><br><span class="line">        &lt;artifactId&gt;spring-core&lt;/artifactId&gt;</span><br><span class="line">        &lt;version&gt;$&#123;spring.version&#125;&lt;/version&gt;</span><br><span class="line">    &lt;/dependency&gt;</span><br><span class="line">    &lt;dependency&gt;</span><br><span class="line">        &lt;groupId&gt;$&#123;spring.group&#125;&lt;/groupId&gt;</span><br><span class="line">        &lt;artifactId&gt;spring-beans&lt;/artifactId&gt;</span><br><span class="line">        &lt;version&gt;$&#123;spring.version&#125;&lt;/version&gt;</span><br><span class="line">    &lt;/dependency&gt;</span><br><span class="line">    &lt;dependency&gt;</span><br><span class="line">        &lt;groupId&gt;$&#123;spring.group&#125;&lt;/groupId&gt;</span><br><span class="line">        &lt;artifactId&gt;spring-aop&lt;/artifactId&gt;</span><br><span class="line">        &lt;version&gt;$&#123;spring.version&#125;&lt;/version&gt;</span><br><span class="line">    &lt;/dependency&gt;</span><br><span class="line">&lt;/dependencies&gt;</span><br></pre></td></tr></table></figure><p>上面的代码，<code>properties</code>位于pom.xml中的，是<code>project</code>元素的子元素，用户可以在<code>properties</code>中自定义一些用户属性，然后可以在其他地方使用<code>${属性名称}</code>这种方式进行引用。</p><h1 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h1><p>我们开发一个项目的时候，通常有这些环节：创建项目、编写代码、清理已编译的代码、编译代码、执行单元测试、打包、集成测试、验证、部署、生成站点等，这些环节组成了项目的生命周期，这些过程也叫做项目的<strong>构建过程</strong>，几乎所有的项目都由这些环节中的其中几个，创建项目和编写代码是我们程序员需要多参与的，其他的都可以做成自动化的方式。</p><p>用过ant的朋友回忆一下，在maven出现以前，开发人员每天都在对项目进行清理、编译、执行单元测试、打包、部署等操作，虽然大家都在做这些工作，但是没有一个统一的标准，项目和项目之间，公司和公司之间，大多数都是各写各的，写法是千奇百怪，能满足自身需求就可以了，但是换个项目就得从头再来，这些操作又需要重新编写脚本。</p><p>而maven出来之后，项目生命周期中的这些环节都被简化了，被规范化了，maven出现之前，项目的结构没有一个统一的标准，所以生命周期中各个环节对应的自动化脚本也是各种各样，而maven约定好了项目的结构，源码的位置、资源文件的位置、测试代码的位置、测试用到的资源文件的位置、静态资源的位置、打包之后文件的位置等，这些都是maven约定好的，所以清理代码用一个命令<code>mvn clean</code>就可以完成，不需要我们去配置清理的目标目录；用<code>mvn compile</code>命令就可以完成编译的操作；用<code>mvn test</code>就可以自动运行测试用例；用<code>mvn package</code>就可以将项目打包为<code>jar、war</code>格式的包，能够如此简单，主要还是maven中约定大于配置的结果。</p><h1 id="maven中生命周期详解"><a href="#maven中生命周期详解" class="headerlink" title="maven中生命周期详解"></a>maven中生命周期详解</h1><p>maven将项目的生命周期抽象成了3套生命周期，每套生命周期又包含多个阶段，每套中具体包含哪些阶段是maven已经约定好的，但是每个阶段具体需要做什么，是用户可以自己指定的。</p><p>maven中定义的3套生命周期：</p><ol><li><p><strong>clean生命周期</strong></p></li><li><p><strong>default生命周期</strong></p></li><li><p><strong>site生命周期</strong></p></li></ol><p>上面这3套生命周期是相互独立的，没有依赖关系的，而每套生命周期中有多个阶段，每套中的多个阶段是有先后顺序的，并且后面的阶段依赖于前面的阶段，而用户可以直接使用<code>mvn</code>命令来调用这些阶段去完成项目生命周期中具体的操作，命令是：</p><pre><code>mvn 生命周期阶段</code></pre><blockquote><p> <strong>通俗点解释：</strong></p><p>maven中的3套生命周期相当于maven定义了3个类来解决项目生命周期中需要的各种操作，每个类中有多个方法，这些方法就是指具体的阶段，方法名称就是阶段的名称，每个类的方法是有顺序的，当执行某个方法的时候，这个方法前面的方法也会执行。具体每个方法中需要执行什么，这个是通过插件的方式让用户去配置的，所以非常灵活。</p><p>用户执行<code>mvn 阶段名称</code>就相当于调用了具体的某个方法。</p></blockquote><p>下面我们来看看每个生命周期中有哪些阶段（也就是我们说的每个类中有哪些方法，顺序是什么样的）。</p><h2 id="clean生命周期"><a href="#clean生命周期" class="headerlink" title="clean生命周期"></a>clean生命周期</h2><p>clean生命周期的目的是清理项目，它包含三个阶段：</p><table><thead><tr><th>生命周期阶段</th><th>描述</th></tr></thead><tbody><tr><td>pre-clean</td><td>执行一些需要在clean之前完成的工作</td></tr><tr><td>clean</td><td>移除所有上一次构建生成的文件</td></tr><tr><td>post-clean</td><td>执行一些需要在clean之后立刻完成的工作</td></tr></tbody></table><p>用户可以通过<code>mvn pre-clean</code>来调用clean生命周期中的<code>pre-clean</code>阶段需要执行的操作。</p><p>调用<code>mvn post-clean</code>会执行上面3个阶段所有的操作，上文中有说过，每个生命周期中的后面的阶段会依赖于前面的阶段，当执行某个阶段的时候，会先执行其前面的阶段。</p><h2 id="default生命周期"><a href="#default生命周期" class="headerlink" title="default生命周期"></a>default生命周期</h2><p>这个是maven主要的生命周期，主要被用于构建应用，包含了23个阶段。</p><table><thead><tr><th>生命周期阶段</th><th>描述</th></tr></thead><tbody><tr><td>validate</td><td>校验：校验项目是否正确并且所有必要的信息可以完成项目的构建过程。</td></tr><tr><td>initialize</td><td>初始化：初始化构建状态，比如设置属性值。</td></tr><tr><td>generate-sources</td><td>生成源代码：生成包含在编译阶段中的任何源代码。</td></tr><tr><td>process-sources</td><td>处理源代码：处理源代码，比如说，过滤任意值。</td></tr><tr><td>generate-resources</td><td>生成资源文件：生成将会包含在项目包中的资源文件。</td></tr><tr><td>process-resources</td><td>编译：复制和处理资源到目标目录，为打包阶段最好准备。</td></tr><tr><td>compile</td><td>处理类文件：编译项目的源代码。</td></tr><tr><td>process-classes</td><td>处理类文件：处理编译生成的文件，比如说对Java class文件做字节码改善优化。</td></tr><tr><td>generate-test-sources</td><td>生成测试源代码：生成包含在编译阶段中的任何测试源代码。</td></tr><tr><td>process-test-sources</td><td>处理测试源代码：处理测试源代码，比如说，过滤任意值。</td></tr><tr><td>generate-test-resources</td><td>生成测试源文件：为测试创建资源文件。</td></tr><tr><td>process-test-resources</td><td>处理测试源文件：复制和处理测试资源到目标目录。</td></tr><tr><td>test-compile</td><td>编译测试源码：编译测试源代码到测试目标目录。</td></tr><tr><td>process-test-classes</td><td>处理测试类文件：处理测试源码编译生成的文件。</td></tr><tr><td>test</td><td>测试：使用合适的单元测试框架运行测试（Juint是其中之一）。</td></tr><tr><td>prepare-package</td><td>准备打包：在实际打包之前，执行任何的必要的操作为打包做准备。</td></tr><tr><td>package</td><td>打包：将编译后的代码打包成可分发格式的文件，比如JAR、WAR或者EAR文件。</td></tr><tr><td>pre-integration-test</td><td>集成测试前：在执行集成测试前进行必要的动作。比如说，搭建需要的环境。</td></tr><tr><td>integration-test</td><td>集成测试：处理和部署项目到可以运行集成测试环境中。</td></tr><tr><td>post-integration-test</td><td>集成测试后：在执行集成测试完成后进行必要的动作。比如说，清理集成测试环境。</td></tr><tr><td>verify</td><td>验证：运行任意的检查来验证项目包有效且达到质量标准。</td></tr><tr><td>install</td><td>安装：安装项目包到本地仓库，这样项目包可以用作其他本地项目的依赖。</td></tr><tr><td>deploy</td><td>部署：将最终的项目包复制到远程仓库中与其他开发者和项目共享。</td></tr></tbody></table><h2 id="site生命周期"><a href="#site生命周期" class="headerlink" title="site生命周期"></a>site生命周期</h2><p>site生命周期的目的是建立和发布项目站点，Maven能够基于pom.xml所包含的信息，自动生成一个友好的站点，方便团队交流和发布项目信息。主要包含以下4个阶段：</p><table><thead><tr><th>阶段</th><th>描述</th></tr></thead><tbody><tr><td>pre-site</td><td>执行一些需要在生成站点文档之前完成的工作</td></tr><tr><td>site</td><td>生成项目的站点文档</td></tr><tr><td>post-site</td><td>执行一些需要在生成站点文档之后完成的工作，并且为部署做准备</td></tr><tr><td>site-deploy</td><td>将生成的站点文档部署到特定的服务器上</td></tr></tbody></table><h2 id="mvn命令和生命周期"><a href="#mvn命令和生命周期" class="headerlink" title="mvn命令和生命周期"></a>mvn命令和生命周期</h2><p>从命令行执行maven任务的最主要方式就是调用maven生命周期的阶段，需要注意的是，每套生命周期是相互独立的，但是每套生命周期中阶段是有前后依赖关系的，执行某个的时候，会按序先执行其前面所有的。</p><p>mvn执行阶段的命令格式是：</p><pre><code>mvn 阶段1 [阶段2] [阶段n]</code></pre><blockquote><p>多个阶段的名称之间用空格隔开。</p></blockquote><p>下面我们举一些常见的例子来说明一下：</p><h3 id="mvn-clean"><a href="#mvn-clean" class="headerlink" title="mvn clean"></a>mvn clean</h3><p>该命令是调用clean生命周期的clean阶段，实际执行的阶段为clean生命周期中的pre-clean和clean阶段。</p><h3 id="mvn-test"><a href="#mvn-test" class="headerlink" title="mvn test"></a>mvn test</h3><p>该命令调用default生命周期的test阶段，实际上会从default生命周期的第一个阶段（<code>validate</code>）开始执行一直到<code>test</code>阶段结束。这里面包含了代码的编译，运行测试用例。</p><h3 id="mvn-clean-install"><a href="#mvn-clean-install" class="headerlink" title="mvn clean install"></a>mvn clean install</h3><p>这个命令中执行了两个阶段：<code>clean</code>和<code>install</code>，从上面3个生命周期的阶段列表中找一下，可以看出<code>clean</code>位于<code>clean</code>生命周期的表格中，<code>install</code>位于<code>default</code>生命周期的表格中，所以这个命令会先从<code>clean</code>生命周期中的<code>pre-clean</code>阶段开始执行一直到<code>clean</code>生命周期的<code>clean</code>阶段；然后会继续从<code>default</code>生命周期的<code>validate</code>阶段开始执行一直到default生命周期的<code>install</code>阶段。</p><p>这里面包含了清理上次构建的结果，编译代码，测试，打包，将打好的包安装到本地仓库。</p><h3 id="mvn-clean-deploy"><a href="#mvn-clean-deploy" class="headerlink" title="mvn clean deploy"></a>mvn clean deploy</h3><p>这个命令也比较常用，会先按顺序执行<code>clean</code>生命周期的<code>[pre-clean,clean]</code>这个闭区间内所有的阶段，然后按序执行<code>default</code>生命周期的<code>[validate,deploy]</code>这个闭区间内的所有阶段（也就是<code>default</code>生命周期中的所有阶段）。这个命令内部包含了清理上次构建的结果、编译代码、运行单元测试、打包、将打好的包安装到本地仓库、将打好的包发布到私服仓库。</p><p>上面说了这么多理论，我们来看一下效果。</p><h2 id="案例"><a href="#案例" class="headerlink" title="案例"></a>案例</h2><h3 id="创建一个maven项目"><a href="#创建一个maven项目" class="headerlink" title="创建一个maven项目"></a>创建一个maven项目</h3><p>打开idea，点击<code>File-&gt;New-&gt;Project</code>，选择<code>Maven</code>，如下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/39f7d0cab6907d834efa4a4dba21142e.jpeg" alt title>                </div>                <div class="image-caption"></div>            </figure><p>点击<code>Next</code>，输入项目坐标信息，如下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/c7587e99eb5976e373ef8b4d50814d50.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>点击<code>Next</code>，输入Project name 为<code>maven-chat06</code>，如下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/46bd60f2fd1d3938c7c67c2a51d8e199.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>点击<code>Finish</code>，创建成功，如下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/5889314e3481d39f6d590d0b8576cf54.jpeg" alt title>                </div>                <div class="image-caption"></div>            </figure><p>配置一下idea的maven环境，点击<code>File-&gt;Settings</code>，如下图：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/ce78117d6f0a355d1eb2f0c28cb204e8.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>点击上面的<code>OK</code>完成配置。</p><p>还原<code>~/.m2/settings.xml</code>的配置到初始状态，操作如下：</p><blockquote><p>将M2_HOME/conf/settings.xml复制到~/.m2/settings.xml目录，如果存在先备份一个，然后进行覆盖。</p></blockquote><p>maven项目是约定大于配置的，项目结构是按照maven的约定生成好的，关于maven约定项目结构，我们再来回顾一下。</p><p>Maven 提倡使用一个共同的标准目录结构，Maven 使用约定优于配置的原则，大家尽可能的遵守这样的目录结构，如下所示：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/340f7e58083e35cf5f7efe179b47bad7.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>结合刚才项目的结构和这个表格领会一下，下面我们来感受一下执行生命周期中的阶段产生的效果。</p><p>修改pom.xml，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><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">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="line">&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;</span><br><span class="line">         xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span><br><span class="line">         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;</span><br><span class="line">    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;groupId&gt;com.javacode2018&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;maven-chat06&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;</span><br><span class="line">    &lt;packaging&gt;jar&lt;/packaging&gt;</span><br><span class="line">    &lt;properties&gt;</span><br><span class="line">        &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;</span><br><span class="line">        &lt;!-- 配置maven编译的时候采用的编译器版本 --&gt;</span><br><span class="line">        &lt;maven.compiler.compilerVersion&gt;1.8&lt;/maven.compiler.compilerVersion&gt;</span><br><span class="line">        &lt;!-- 指定源代码是什么版本的，如果源码和这个版本不符将报错，maven中执行编译的时候会用到这个配置，默认是1.5，这个相当于javac命令后面的-source参数 --&gt;</span><br><span class="line">        &lt;maven.compiler.source&gt;1.8&lt;/maven.compiler.source&gt;</span><br><span class="line">        &lt;!-- 该命令用于指定生成的class文件将保证和哪个版本的虚拟机进行兼容，maven中执行编译的时候会用到这个配置，默认是1.5，这个相当于javac命令后面的-target参数 --&gt;</span><br><span class="line">        &lt;maven.compiler.target&gt;1.8&lt;/maven.compiler.target&gt;</span><br><span class="line">    &lt;/properties&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;dependencies&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;junit&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;junit&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;4.12&lt;/version&gt;</span><br><span class="line">            &lt;scope&gt;test&lt;/scope&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">    &lt;/dependencies&gt;</span><br><span class="line"> </span><br><span class="line">&lt;/project&gt;</span><br></pre></td></tr></table></figure><blockquote><p>上面properties这个元素中的配置，可能大家看不懂，先略过，后面会详解。</p></blockquote><p>创建一个Demo类，源码是放在src/main/java目录中，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">package com.javacode2018.maven;</span><br><span class="line"> </span><br><span class="line">import java.util.ArrayList;</span><br><span class="line">import java.util.List;</span><br><span class="line"> </span><br><span class="line">public class Demo1 &#123;</span><br><span class="line">    public static void main(String[] args) &#123;</span><br><span class="line">        System.out.println(&quot;hello world!&quot;);</span><br><span class="line">        List&lt;Integer&gt; list = new ArrayList&lt;&gt;();</span><br><span class="line">        for (int i = 0; i &lt; 5; i++) &#123;</span><br><span class="line">            list.add(i);</span><br><span class="line">        &#125;</span><br><span class="line">        list.forEach(System.out::print);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="mvn-clean命令效果"><a href="#mvn-clean命令效果" class="headerlink" title="mvn clean命令效果"></a>mvn clean命令效果</h3><p>在当前项目pom.xml所在目录中执行下面命令：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn clean</span><br></pre></td></tr></table></figure><p>效果如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn clean</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-chat06 ---</span><br><span class="line">[INFO] Deleting D:\code\IdeaProjects\maven-chat06\target</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  0.477 s</span><br><span class="line">[INFO] Finished at: 2019-11-15T18:46:13+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>上面有提到编译、打包的内容都放在<code>target</code>目录，看上面输出中有个<code>Deleting target目录</code>，说明<code>mvn clean</code>是对这个目录进行清理，这个目录中目前是空的。</p><h3 id="mvn-compile命令效果"><a href="#mvn-compile命令效果" class="headerlink" title="mvn compile命令效果"></a>mvn compile命令效果</h3><p>先看一下项目的目录中是没有target目录的，如下图：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/8bffdba874c6ee2e3fe6c7e19cc038a8.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>cmd中执行：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn compile</span><br></pre></td></tr></table></figure><p>输出：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn compile</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat06 ---</span><br><span class="line">[INFO] Changes detected - recompiling the module!</span><br><span class="line">[INFO] Compiling 1 source file to D:\code\IdeaProjects\maven-chat06\target\classes</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  1.897 s</span><br><span class="line">[INFO] Finished at: 2019-11-15T18:53:12+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>可以看到上面有<code>Compiling 1 source ....</code>，这个是编译<code>Demo.java</code>，然后输出到了target中的classes目录，再来看一下项目的结构，如下图：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/7d1cbf02b158a234d5970897f21a22bf.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>上图中匡红的是新生成的。</p><h3 id="mvn-clean-package效果"><a href="#mvn-clean-package效果" class="headerlink" title="mvn clean package效果"></a>mvn clean package效果</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><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">D:\code\IdeaProjects\maven-chat06&gt;mvn clean package</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-chat06 ---</span><br><span class="line">[INFO] Deleting D:\code\IdeaProjects\maven-chat06\target</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat06 ---</span><br><span class="line">[INFO] Changes detected - recompiling the module!</span><br><span class="line">[INFO] Compiling 1 source file to D:\code\IdeaProjects\maven-chat06\target\classes</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ maven-chat06 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-chat06 ---</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ maven-chat06 ---</span><br><span class="line">[INFO] Building jar: D:\code\IdeaProjects\maven-chat06\target\maven-chat06-1.0-SNAPSHOT.jar</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  2.177 s</span><br><span class="line">[INFO] Finished at: 2019-11-15T18:56:59+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>从输出中看一下，有个<code>Building jar ...</code>，生成了一个jar包，这个项目的pom.xml中的packaging元素没有指定值，那就取默认值jar，表示这个构件是一个jar包，<code>mvn clean package</code>先清理编译的代码，然后执行了default生命周期的<code>compile</code>阶段，将项目打成了jar放在了target目录，如下图：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/6b55221b35e46e5b9bc24b5da19f63cc.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>大家看到上面还有很多其他的输出，这个大家可以先忽略，本文看完了，都会明白的。</p><h3 id="mvn-clean-install效果"><a href="#mvn-clean-install效果" class="headerlink" title="mvn clean install效果"></a>mvn clean install效果</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn clean install</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-chat06 ---</span><br><span class="line">[INFO] Deleting D:\code\IdeaProjects\maven-chat06\target</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat06 ---</span><br><span class="line">[INFO] Changes detected - recompiling the module!</span><br><span class="line">[INFO] Compiling 1 source file to D:\code\IdeaProjects\maven-chat06\target\classes</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ maven-chat06 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-chat06 ---</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ maven-chat06 ---</span><br><span class="line">[INFO] Building jar: D:\code\IdeaProjects\maven-chat06\target\maven-chat06-1.0-SNAPSHOT.jar</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-install-plugin:2.4:install (default-install) @ maven-chat06 ---</span><br><span class="line">[INFO] Installing D:\code\IdeaProjects\maven-chat06\target\maven-chat06-1.0-SNAPSHOT.jar to C:\Users\Think\.m2\repository\com\javacode2018\maven-chat06\1.0-SNAPSHOT\maven-chat06-1.0-SNAPSHOT.jar</span><br><span class="line">[INFO] Installing D:\code\IdeaProjects\maven-chat06\pom.xml to C:\Users\Think\.m2\repository\com\javacode2018\maven-chat06\1.0-SNAPSHOT\maven-chat06-1.0-SNAPSHOT.pom</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  2.977 s</span><br><span class="line">[INFO] Finished at: 2019-11-15T19:05:21+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>和<code>mvn clean package</code>的输出对比一下，多了几行输出，主要是多了2个<code>Installing...</code>，将项目打成jar包以及项目的pom文件放到本地仓库去了，也就是将构件打包安装到本地仓库了。</p><p>上面几个mvn命令的案例，都是通过mvn命令去执行了mvn中定义的生命周期中的阶段，然后完成了很多看似内部很复杂的操作。比如打包，内部包含很多复杂的操作，maven都帮我们屏蔽了，通过一个简单的<code>mvn package</code>就完成了。</p><p>上面也有说过，每个阶段具体做的事情是由maven插件来完成的。</p><p>我们在回头看一下上面一个输出中，有很多类似于<code>maven-xxxx-plugin:版本:xxx</code>这样的内容，这个就是表示当前在运行这个插件来完成对应阶段的操作，<code>mvn 阶段</code>明明执行的是阶段，但是实际输出中确实插件在干活，那么阶段是如何和插件关联起来的呢？插件又是什么呢？</p><p><strong>注意以下所有命令都在cmd窗口执行，执行位置位于上面这个项目的pom.xml所在目录。</strong></p><h1 id="Maven插件"><a href="#Maven插件" class="headerlink" title="Maven插件"></a>Maven插件</h1><p>maven插件主要是为maven中生命周期中的阶段服务的，maven中只是定义了3套生命周期，以及每套生命周期中有哪些阶段，具体每个阶段中执行什么操作，完全是交给插件去干的。</p><p>maven中的插件就相当于一些工具，比如编译代码的工具，运行测试用例的工具，打包代码的工具，将代码上传到本地仓库的工具，将代码部署到远程仓库的工具等等，这些都是maven中的插件。</p><p>插件可以通过<code>mvn</code>命令的方式调用直接运行，或者将插件和maven生命周期的阶段进行绑定，然后通过<code>mvn 阶段</code>的方式执行阶段的时候，会自动执行和这些阶段绑定的插件。</p><h2 id="插件目标"><a href="#插件目标" class="headerlink" title="插件目标"></a>插件目标</h2><p>maven中的插件以jar的方式存在于仓库中，和其他构件是一样的，也是通过坐标进行访问，每个插件中可能为了代码可以重用，一个插件可能包含了多个功能，比如编译代码的插件，可以编译源代码、也可以编译测试代码；<strong>插件中的每个功能就叫做插件的目标（Plugin Goal），每个插件中可能包含一个或者多个插件目标（Plugin Goal）</strong>。</p><h3 id="目标参数"><a href="#目标参数" class="headerlink" title="目标参数"></a>目标参数</h3><p>插件目标是用来执行任务的，那么执行任务肯定是有参数配的，这些就是目标的参数，每个插件目标对应于java中的一个类，参数就对应于这个类中的属性。</p><h3 id="列出插件所有目标"><a href="#列出插件所有目标" class="headerlink" title="列出插件所有目标"></a>列出插件所有目标</h3><figure class="highlight plain"><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">mvn 插件goupId:插件artifactId[:插件version]:help</span><br><span class="line">mvn 插件前缀:help</span><br></pre></td></tr></table></figure><blockquote><p>上面插件前缀的先略过，我们先看第一种效果。</p></blockquote><p>如：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn org.apache.maven.plugins:maven-clean-plugin:help</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-clean-plugin:2.5:help (default-cli) @ maven-chat06 ---</span><br><span class="line">[INFO] org.apache.maven.plugins:maven-clean-plugin:2.5</span><br><span class="line"> </span><br><span class="line">Maven Clean Plugin</span><br><span class="line">  The Maven Clean Plugin is a plugin that removes files generated at build-time</span><br><span class="line">  in a project&apos;s directory.</span><br><span class="line">This plugin has 2 goals:</span><br><span class="line">clean:clean</span><br><span class="line">  Goal which cleans the build.</span><br><span class="line">  This attempts to clean a project&apos;s working directory of the files that were</span><br><span class="line">  generated at build-time. By default, it discovers and deletes the directories</span><br><span class="line">  configured in project.build.directory, project.build.outputDirectory,</span><br><span class="line">  project.build.testOutputDirectory, and project.reporting.outputDirectory.</span><br><span class="line"> </span><br><span class="line">  Files outside the default may also be included in the deletion by configuring</span><br><span class="line">  the filesets tag.</span><br><span class="line"> </span><br><span class="line">clean:help</span><br><span class="line">  Display help information on maven-clean-plugin.</span><br><span class="line">  Call</span><br><span class="line">    mvn clean:help -Ddetail=true -Dgoal=&lt;goal-name&gt;</span><br><span class="line">  to display parameter details.</span><br></pre></td></tr></table></figure><blockquote><p>上面列出了<code>maven-clean-plugin</code>这个插件所有的目标，有2个，分别是<code>clean:clean、clean:help</code>，分号后面的部分是目标名称，分号前面的部分是插件的前缀，每个目标的后面包含对这个目标的详细解释说明，关于前缀的后面会有详细介绍。</p></blockquote><h3 id="查看插件目标参数列表"><a href="#查看插件目标参数列表" class="headerlink" title="查看插件目标参数列表"></a>查看插件目标参数列表</h3><figure class="highlight plain"><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">mvn 插件goupId:插件artifactId[:插件version]:help -Dgoal=目标名称 -Ddetail</span><br><span class="line">mvn 插件前缀:help -Dgoal=目标名称 -Ddetail</span><br></pre></td></tr></table></figure><blockquote><p>上面命令中的<code>-Ddetail</code>用户输出目标详细的参数列表信息，如果没有这个，目标的参数列表不会输出出来，看效果。</p></blockquote><p>如：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn org.apache.maven.plugins:maven-clean-plugin:help -Dgoal=help -Ddetail</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-clean-plugin:2.5:help (default-cli) @ maven-chat06 ---</span><br><span class="line">[INFO] org.apache.maven.plugins:maven-clean-plugin:2.5</span><br><span class="line"> </span><br><span class="line">Maven Clean Plugin</span><br><span class="line">  The Maven Clean Plugin is a plugin that removes files generated at build-time</span><br><span class="line">  in a project&apos;s directory.</span><br><span class="line">clean:help</span><br><span class="line">  Display help information on maven-clean-plugin.</span><br><span class="line">  Call</span><br><span class="line">    mvn clean:help -Ddetail=true -Dgoal=&lt;goal-name&gt;</span><br><span class="line">  to display parameter details.</span><br><span class="line">  Available parameters:</span><br><span class="line">    detail (Default: false)</span><br><span class="line">      If true, display all settable properties for each goal.</span><br><span class="line">      Expression: $&#123;detail&#125;</span><br><span class="line">    goal</span><br><span class="line">      The name of the goal for which to show help. If unspecified, all goals</span><br><span class="line">      will be displayed.</span><br><span class="line">      Expression: $&#123;goal&#125;</span><br><span class="line">    indentSize (Default: 2)</span><br><span class="line">      The number of spaces per indentation level, should be positive.</span><br><span class="line">      Expression: $&#123;indentSize&#125;</span><br><span class="line">    lineLength (Default: 80)</span><br><span class="line">      The maximum length of a display line, should be positive.</span><br><span class="line">      Expression: $&#123;lineLength&#125;</span><br></pre></td></tr></table></figure><p>上面列出了<code>clean</code>插件的<code>help</code>目标的详细参数信息。</p><p>注意上面参数详细参数说明中有<code>Expression: ${xxx}</code>这样的部分，这种表示给这个运行的目标传参，可以通过<code>mvn -Dxxx</code>这种方式传参，<code>xxx</code>为<code>${xxx}</code>中的<code>xxx</code>部分，这个<code>xxx</code>有时候和目标参数的名称不一致，所以这点需要注意，运行带参数的目标，看一下效果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn org.apache.maven.plugins:maven-clean-plugin:help -Dgoal=help -Ddetail=false</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-clean-plugin:2.5:help (default-cli) @ maven-chat06 ---</span><br><span class="line">[INFO] org.apache.maven.plugins:maven-clean-plugin:2.5</span><br><span class="line"> </span><br><span class="line">Maven Clean Plugin</span><br><span class="line">  The Maven Clean Plugin is a plugin that removes files generated at build-time</span><br><span class="line">  in a project&apos;s directory.</span><br><span class="line">clean:help</span><br><span class="line">  Display help information on maven-clean-plugin.</span><br><span class="line">  Call</span><br><span class="line">    mvn clean:help -Ddetail=true -Dgoal=&lt;goal-name&gt;</span><br><span class="line">  to display parameter details.</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  0.332 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T15:14:56+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>上面传了一个<code>detail=false</code>，上面未输出目标的详细参数信息。</p><h3 id="命令行运行插件"><a href="#命令行运行插件" class="headerlink" title="命令行运行插件"></a>命令行运行插件</h3><figure class="highlight plain"><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">mvn 插件goupId:插件artifactId[:插件version]:插件目标 [-D目标参数1] [-D目标参数2] [-D目标参数n]</span><br><span class="line">mvn 插件前缀:插件目标  [-D目标参数1] [-D目标参数2] [-D目标参数n]</span><br></pre></td></tr></table></figure><p>案例：</p><p>maven中运行测试用例使用到的插件坐标是：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;2.12.4&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure><p>我们看一下这个插件有哪些目标：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn org.apache.maven.plugins:maven-surefire-plugin:help</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:help (default-cli) @ maven-chat06 ---</span><br><span class="line">[INFO] Maven Surefire Plugin 2.12.4</span><br><span class="line">  Surefire is a test framework project.</span><br><span class="line"> </span><br><span class="line">This plugin has 2 goals:</span><br><span class="line"> </span><br><span class="line">surefire:help</span><br><span class="line">  Display help information on maven-surefire-plugin.</span><br><span class="line">  Call mvn surefire:help -Ddetail=true -Dgoal=&lt;goal-name&gt; to display parameter</span><br><span class="line">  details.</span><br><span class="line"> </span><br><span class="line">surefire:test</span><br><span class="line">  Run tests using Surefire.</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  0.662 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T15:26:26+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><blockquote><p>maven-surefire-plugin插件有2个目标<code>help</code>和<code>test</code>，描述中可以看出<code>test</code>目标是用来运行测试用例的。</p></blockquote><p>我们看一下<code>test</code>目标对应的参数列表：</p><blockquote><p>test目标对应的参数太多，我们只列出了部分参数，如下：</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn org.apache.maven.plugins:maven-surefire-plugin:help -Dgoal=test -Ddetail=true</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:help (default-cli) @ maven-chat06 ---</span><br><span class="line">[INFO] Maven Surefire Plugin 2.12.4</span><br><span class="line">  Surefire is a test framework project.</span><br><span class="line"> </span><br><span class="line">surefire:test</span><br><span class="line">  Run tests using Surefire.</span><br><span class="line"> </span><br><span class="line">  Available parameters:</span><br><span class="line"> </span><br><span class="line">    skip (Default: false)</span><br><span class="line">      Set this to &apos;true&apos; to bypass unit tests entirely. Its use is NOT</span><br><span class="line">      RECOMMENDED, especially if you enable it using the &apos;maven.test.skip&apos;</span><br><span class="line">      property, because maven.test.skip disables both running the tests and</span><br><span class="line">      compiling the tests. Consider using the skipTests parameter instead.</span><br></pre></td></tr></table></figure><blockquote><p>认真看一下<code>skip</code>这个参数说明，这个参数默认是false，如果设置为<code>true</code>的时候，项目将跳过<code>测试代码的编译和测试用例的执行</code>，可以<code>maven.test.skip</code>这个属性来进行命令行传参，将其传递给<code>test</code>目标的<code>skip</code>属性，这个通过<code>-D</code>传递的参数名称就和目标参数名称不一样了，所以需要注意<code>-D</code>后面并不一定是参数名称。</p></blockquote><p>我们来运行一下test目标看看效果。</p><p>先看一下不加参数的效果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn org.apache.maven.plugins:maven-surefire-plugin:test</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:test (default-cli) @ maven-chat06 ---</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  0.640 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T15:33:48+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>加<code>maven.skip.test=true</code>的效果如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn org.apache.maven.plugins:maven-surefire-plugin:test -Dmaven.test.skip=true</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:test (default-cli) @ maven-chat06 ---</span><br><span class="line">[INFO] Tests are skipped.</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  0.652 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T15:34:45+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>对比一下上面2个输出，下面的多了一行如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[INFO] Tests are skipped.</span><br></pre></td></tr></table></figure><p>说明跳过了测试的执行。</p><h3 id="插件传参的2种方式"><a href="#插件传参的2种方式" class="headerlink" title="插件传参的2种方式"></a>插件传参的2种方式</h3><p>刚才上面讲了一种通过<code>-D</code>后面跟用户属性的方式给用户传参，还有一种方式，在pom.xml中<code>properties</code>的用户自定义属性中进行配置，如下：</p><p>修改项目<code>maven-chat06</code>的pom.xml，<code>properties</code>中加入：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;maven.test.skip&gt;true&lt;/maven.test.skip&gt;</span><br></pre></td></tr></table></figure><p>cmd中运行：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn org.apache.maven.plugins:maven-surefire-plugin:test</span><br></pre></td></tr></table></figure><p>效果如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn org.apache.maven.plugins:maven-surefire-plugin:test</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:test (default-cli) @ maven-chat06 ---</span><br><span class="line">[INFO] Tests are skipped.</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  0.638 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T15:46:04+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>输出中也有<code>Tests are skipped.</code>，说明也跳过了测试，和<code>-Dmaven.test.skip=true</code>效果一样。</p><p>上面说的都是插件目标的东西，那么插件目标是如何和生命周期关联起来的呢？继续向下看。</p><h3 id="获取插件目标详细描述信息的另外一种方式"><a href="#获取插件目标详细描述信息的另外一种方式" class="headerlink" title="获取插件目标详细描述信息的另外一种方式"></a>获取插件目标详细描述信息的另外一种方式</h3><figure class="highlight plain"><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">mvn help:describe -Dplugin=插件goupId:插件artifactId[:插件version] -Dgoal=目标名称 -Ddetail</span><br><span class="line">mvn help:describe -Dplugin=插件前缀 -Dgoal=目标名称 -Ddetail</span><br></pre></td></tr></table></figure><blockquote><p>上面这个命令调用的是help插件的<code>describe</code>这个目标，这个目标可以列出其他指定插件目标的详细信息，看效果：</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><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">D:\code\IdeaProjects\maven-chat06&gt;mvn help:describe -Dplugin=org.apache.maven.plugins:maven-surefire-plugin -Dgoal=test -Ddetail</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-help-plugin:3.2.0:describe (default-cli) @ maven-chat06 ---</span><br><span class="line">[INFO] Mojo: &apos;surefire:test&apos;</span><br><span class="line">surefire:test</span><br><span class="line">  Description: Run tests using Surefire.</span><br><span class="line">  Implementation: org.apache.maven.plugin.surefire.SurefirePlugin</span><br><span class="line">  Language: java</span><br><span class="line">  Bound to phase: test</span><br><span class="line"> </span><br><span class="line">  Available parameters:</span><br><span class="line"> </span><br><span class="line">    additionalClasspathElements</span><br><span class="line">      Additional elements to be appended to the classpath.</span><br><span class="line"> </span><br><span class="line">    argLine</span><br><span class="line">      User property: argLine</span><br><span class="line">      Arbitrary JVM options to set on the command line.</span><br><span class="line"> </span><br><span class="line">    skip (Default: false)</span><br><span class="line">      User property: maven.test.skip</span><br><span class="line">      Set this to &apos;true&apos; to bypass unit tests entirely. Its use is NOT</span><br><span class="line">      RECOMMENDED, especially if you enable it using the &apos;maven.test.skip&apos;</span><br><span class="line">      property, because maven.test.skip disables both running the tests and</span><br><span class="line">      compiling the tests. Consider using the skipTests parameter instead.</span><br></pre></td></tr></table></figure><p>可以拿这种和上面获取插件目标参数详情列表对比一下，上面这个更详细一些，参数说明中多了一行<code>User property: 属性名称</code>，这个属性名称可以通过两种方式传递：</p><ol><li><p>mvn命令<code>-D属性名称</code>的方式传递</p></li><li><p>pom.xml中<code>properties</code>中定义的方式指定。</p></li></ol><p>现在可以大家估计可以知道我们一直用的<code>-Dmaven.test.skip</code>为什么可以跳过测试代码的编译和单元测试的执行了吧。</p><h2 id="插件前缀"><a href="#插件前缀" class="headerlink" title="插件前缀"></a>插件前缀</h2><p>运行插件的时候，可以通过指定插件坐标的方式运行，但是插件的坐标信息过于复杂，也不方便写和记忆，所以maven中给插件定义了一些简捷的插件前缀，可以通过插件前缀来运行指定的插件。</p><p>可以通过下面命令查看到插件的前缀：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn help:describe -Dplugin=插件goupId:插件artifactId[:插件version]</span><br></pre></td></tr></table></figure><p>示例效果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn help:describe -Dplugin=org.apache.maven.plugins:maven-surefire-plugin</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-help-plugin:3.2.0:describe (default-cli) @ maven-chat06 ---</span><br><span class="line">[INFO] org.apache.maven.plugins:maven-surefire-plugin:2.12.4</span><br><span class="line"> </span><br><span class="line">Name: Maven Surefire Plugin</span><br><span class="line">Description: Surefire is a test framework project.</span><br><span class="line">Group Id: org.apache.maven.plugins</span><br><span class="line">Artifact Id: maven-surefire-plugin</span><br><span class="line">Version: 2.12.4</span><br><span class="line">Goal Prefix: surefire</span><br></pre></td></tr></table></figure><blockquote><p>输出中的<code>Goal Prefix:</code>部分对应的就是插件的前缀，上面这个插件的前缀是<code>surefire</code>。</p></blockquote><p>我们使用前缀来运行一下插件感受一下效果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn surefire:test</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:test (default-cli) @ maven-chat06 ---</span><br><span class="line">[INFO] Tests are skipped.</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  0.934 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T16:18:42+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><blockquote><p>上面通过别名来运行插件<code>maven-surefire-plugin</code>的<code>test</code>目标，是不是简洁了很多。</p></blockquote><p>上面用了很多<code>mvn help:</code>这个命令，这个调用的是<code>maven-help-plugin</code>插件的功能，<code>help</code>是插件的前缀，它的坐标是：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;maven-help-plugin&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;3.2.0&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure><h2 id="插件和生命周期阶段绑定"><a href="#插件和生命周期阶段绑定" class="headerlink" title="插件和生命周期阶段绑定"></a>插件和生命周期阶段绑定</h2><p>maven只是定义了生命周期中的阶段，而没有定义每个阶段中具体的实现，这些实现是由插件的目标来完成的，所以需要将阶段和插件目标进行绑定，来让插件目标帮助生命周期的阶段做具体的工作，生命周期中的每个阶段支持绑定多个插件的多个目标。</p><p><strong>当我们将生命周期中的阶段和插件的目标进行绑定的时候，执行<code>mvn 阶段</code>就可以执行和这些阶段绑定的<code>插件目标</code>。</strong></p><h2 id="maven内置插件以及绑定"><a href="#maven内置插件以及绑定" class="headerlink" title="maven内置插件以及绑定"></a>maven内置插件以及绑定</h2><p>maven为了让我们不用做任何配置就可以实现一些项目的构建操作，比如运行<code>mvn clean</code>就可以帮我们清理代码，运行<code>mvn install</code>就可以将构件安装到本地仓库，所以maven帮我们做了一些事情，maven内部已经提供了很多默认的插件，而将一些阶段默认和这些插件阶段绑定好了，所以我们不用做任何配置就可以执行清理代码、编译代码、测试、打包、安装到本地仓库、上传到远程仓库等阶段的操作，是因为maven已经默认给这些阶段绑定好了插件目标，所以不需要我们再去配置，就直接可以运行，这些都是maven内置绑定帮我们做的事情，我们来看看maven有哪些内置绑定。</p><h2 id="maven内置绑定"><a href="#maven内置绑定" class="headerlink" title="maven内置绑定"></a>maven内置绑定</h2><h3 id="clean生命周期阶段与插件绑定关系"><a href="#clean生命周期阶段与插件绑定关系" class="headerlink" title="clean生命周期阶段与插件绑定关系"></a>clean生命周期阶段与插件绑定关系</h3><table><thead><tr><th>生命周期阶段</th><th>插件:目标</th></tr></thead><tbody><tr><td>pre-clean</td><td>clean</td></tr><tr><td>maven-clean-plugin:clean</td><td>post-clean</td></tr></tbody></table><blockquote><p>clean周期中只有clean阶段默认绑定了<code>maven-clean-plugin</code>插件的<code>clean</code>目标。<code>maven-clean-plugin</code>插件的<code>clean</code>目标作用就是删除项目的输出目录。</p></blockquote><h3 id="default生命周期阶段与插件绑定关系"><a href="#default生命周期阶段与插件绑定关系" class="headerlink" title="default生命周期阶段与插件绑定关系"></a>default生命周期阶段与插件绑定关系</h3><p>default生命周期中有23个阶段，我只列出有默认绑定的，其他的没有列出的没有绑定任何插件，因此没有任何实际的行为。</p><table><thead><tr><th>生命周期阶段</th><th>插件:目标</th><th>执行任务</th></tr></thead><tbody><tr><td>process-resources</td><td>maven-resources-plugin:resources</td><td>复制主资源文件至主输出目录</td></tr><tr><td>compile</td><td>maven-compiler-plugin:compile</td><td>编译主代码至主输出目录</td></tr><tr><td>process-test-resources</td><td>maven-resources-plugin:testResources</td><td>复制测试资源文件至测试输出目录</td></tr><tr><td>test-compile</td><td>maven-compiler-plugin:testCompile</td><td>编译测试代码至测试输出目录</td></tr><tr><td>test</td><td>maven-surefile-plugin:test</td><td>执行测试用例</td></tr><tr><td>package</td><td>maven-jar-plugin:jar</td><td>创建项目jar包</td></tr><tr><td>install</td><td>maven-install-plugin:install</td><td>将输出构件安装到本地仓库</td></tr><tr><td>deploy</td><td>maven-deploy-plugin:deploy</td><td>将输出的构件部署到远程仓库</td></tr></tbody></table><h3 id="site生命周期阶段与插件绑定关系"><a href="#site生命周期阶段与插件绑定关系" class="headerlink" title="site生命周期阶段与插件绑定关系"></a>site生命周期阶段与插件绑定关系</h3><table><thead><tr><th>生命周期阶段</th><th>插件:目标</th></tr></thead><tbody><tr><td>pre-site</td><td></td></tr><tr><td>site</td><td>maven-site-plugin:site</td></tr><tr><td>post-site</td><td></td></tr><tr><td>site-deploy</td><td>maven-site-plugin:deploy</td></tr></tbody></table><p>来几个案例解说一下。</p><h3 id="mvn-clean-1"><a href="#mvn-clean-1" class="headerlink" title="mvn clean"></a>mvn clean</h3><p>该命令是调用clean生命周期的clean阶段，实际执行的阶段为clean生命周期中的pre-clean和clean阶段，从上面内置绑定表格中找一下，可以看到只有<code>clean</code>阶段绑定了<code>maven-clean-plugin</code>插件的<code>clean</code>目标，所以运行<code>mvn clean</code>的时候，实际上会调用<code>maven-clean-plugin</code>插件的<code>clean</code>目标来清理代码。</p><p>运行一下看一下效果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn clean</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-chat06 ---</span><br><span class="line">[INFO] Deleting D:\code\IdeaProjects\maven-chat06\target</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  0.408 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T16:34:14+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>上面有一行输出如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-chat06 ---</span><br></pre></td></tr></table></figure><p>这个表示调用的插件是：<code>maven-clean-plugin</code>，版本是：<code>2.5</code>，插件的目标是：<code>clean</code></p><h3 id="4-5-5、mvn-test"><a href="#4-5-5、mvn-test" class="headerlink" title="4.5.5、mvn test"></a>4.5.5、mvn test</h3><p>该命令调用default生命周期的test阶段，实际上会从default生命周期的第一个阶段（<code>validate</code>）开始执行一直到<code>test</code>阶段结束。这里面包含了代码的编译，运行测试用例。还是和上面的分析过程一样，对照上面表格中的绑定关系，可以得到<code>mvn test</code>会调用下面一些插件的目标：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">maven-resources-plugin:resources</span><br><span class="line">maven-compiler-plugin:compile</span><br><span class="line">maven-resources-plugin:testResources</span><br><span class="line">maven-compiler-plugin:testCompile</span><br><span class="line">maven-surefile-plugin:test</span><br></pre></td></tr></table></figure><p>我们来验证一下，看看是不是和我们分析的一样：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><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">D:\code\IdeaProjects\maven-chat06&gt;mvn test</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat06 ---</span><br><span class="line">[INFO] Changes detected - recompiling the module!</span><br><span class="line">[INFO] Compiling 1 source file to D:\code\IdeaProjects\maven-chat06\target\classes</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ maven-chat06 ---</span><br><span class="line">[INFO] Changes detected - recompiling the module!</span><br><span class="line">[INFO] Compiling 1 source file to D:\code\IdeaProjects\maven-chat06\target\test-classes</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-chat06 ---</span><br><span class="line">[INFO] Tests are skipped.</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  1.880 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T16:36:55+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>从上面输出中可以看到调用了5个插件的目标，和分析的一样。</p><p>再来看一个跳过测试的例子，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn test -Dmaven.skip.test=true</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat06 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ maven-chat06 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-chat06 ---</span><br><span class="line">[INFO] Tests are skipped.</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  1.384 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T16:38:52+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><blockquote><p>上面这个是不是很熟悉，经常用到的跳过测试，为什么这么写，我想大家都知道了吧。</p></blockquote><p>其他几个<code>mvn compile</code>、<code>mvn install</code>、<code>mvn deploy</code>建议大家也自己去玩玩，加深理解。</p><h2 id="自定义绑定"><a href="#自定义绑定" class="headerlink" title="自定义绑定"></a>自定义绑定</h2><p>除了默认绑定的一些操作，我们自己也可以将一些阶段绑定到指定的插件目标上来完成一些操作，这种自定义绑定让maven项目在构件的过程中可以执行更多更丰富的操作。</p><p>常见的一个案例是：创建项目的源码jar包，将其安装到仓库中，内置插件绑定关系中没有涉及到这一步的任务，所以需要用户自己配置。</p><p>插件<code>maven-source-plugin</code>的<code>jar-no-fork</code>可以帮助我们完成该任务，我们将这个目标绑定在<code>default</code>生命周期的<code>verify</code>阶段上面，这个阶段没有任何默认绑定，<code>verify</code>是在测试完成之后并将构件安装到本地仓库之前执行的阶段，在这个阶段我们生成源码，配置如下：</p><p>在<code>maven-chat06</code>中的<code>pom.xml</code>加入如下配置：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&lt;build&gt;</span><br><span class="line">    &lt;plugins&gt;</span><br><span class="line">        &lt;plugin&gt;</span><br><span class="line">            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;maven-source-plugin&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;3.2.0&lt;/version&gt;</span><br><span class="line">            &lt;executions&gt;</span><br><span class="line">                &lt;!-- 使用插件需要执行的任务 --&gt;</span><br><span class="line">                &lt;execution&gt;</span><br><span class="line">                    &lt;!-- 任务id --&gt;</span><br><span class="line">                    &lt;id&gt;attach-source&lt;/id&gt;</span><br><span class="line">                    &lt;!-- 任务中插件的目标，可以指定多个 --&gt;</span><br><span class="line">                    &lt;goals&gt;</span><br><span class="line">                        &lt;goal&gt;jar-no-fork&lt;/goal&gt;</span><br><span class="line">                    &lt;/goals&gt;</span><br><span class="line">                    &lt;!-- 绑定的阶段 --&gt;</span><br><span class="line">                    &lt;phase&gt;verify&lt;/phase&gt;</span><br><span class="line">                &lt;/execution&gt;</span><br><span class="line">            &lt;/executions&gt;</span><br><span class="line">        &lt;/plugin&gt;</span><br><span class="line">    &lt;/plugins&gt;</span><br><span class="line">&lt;/build&gt;</span><br></pre></td></tr></table></figure><blockquote><p>注意上面配置的<code>attach-source</code>，后面输出中会有。</p><p>id：任务的id，需唯一，如果不指定，默认为<code>default</code>。</p><p>每个插件的配置在pom.xml的<code>plugins</code>元素中只能写一次，否则会有警告。</p></blockquote><p>最终pom.xml如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="line">&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;</span><br><span class="line">         xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span><br><span class="line">         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;</span><br><span class="line">    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;groupId&gt;com.javacode2018&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;maven-chat06&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;</span><br><span class="line">    &lt;packaging&gt;jar&lt;/packaging&gt;</span><br><span class="line">    &lt;properties&gt;</span><br><span class="line">        &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;</span><br><span class="line">        &lt;!-- 配置maven编译的时候采用的编译器版本 --&gt;</span><br><span class="line">        &lt;maven.compiler.compilerVersion&gt;1.8&lt;/maven.compiler.compilerVersion&gt;</span><br><span class="line">        &lt;!-- 指定源代码是什么版本的，如果源码和这个版本不符将报错，maven中执行编译的时候会用到这个配置，默认是1.5，这个相当于javac命令后面的-source参数 --&gt;</span><br><span class="line">        &lt;maven.compiler.source&gt;1.8&lt;/maven.compiler.source&gt;</span><br><span class="line">        &lt;!-- 该命令用于指定生成的class文件将保证和哪个版本的虚拟机进行兼容，maven中执行编译的时候会用到这个配置，默认是1.5，这个相当于javac命令后面的-target参数 --&gt;</span><br><span class="line">        &lt;maven.compiler.target&gt;1.8&lt;/maven.compiler.target&gt;</span><br><span class="line">    &lt;/properties&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;dependencies&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;junit&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;junit&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;4.12&lt;/version&gt;</span><br><span class="line">            &lt;scope&gt;test&lt;/scope&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">    &lt;/dependencies&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;build&gt;</span><br><span class="line">        &lt;plugins&gt;</span><br><span class="line">            &lt;plugin&gt;</span><br><span class="line">                &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br><span class="line">                &lt;artifactId&gt;maven-source-plugin&lt;/artifactId&gt;</span><br><span class="line">                &lt;version&gt;3.2.0&lt;/version&gt;</span><br><span class="line">                &lt;executions&gt;</span><br><span class="line">                    &lt;!-- 使用插件需要执行的任务 --&gt;</span><br><span class="line">                    &lt;execution&gt;</span><br><span class="line">                        &lt;!-- 任务id --&gt;</span><br><span class="line">                        &lt;id&gt;attach-source&lt;/id&gt;</span><br><span class="line">                        &lt;!-- 任务中插件的目标，可以指定多个 --&gt;</span><br><span class="line">                        &lt;goals&gt;</span><br><span class="line">                            &lt;goal&gt;jar-no-fork&lt;/goal&gt;</span><br><span class="line">                        &lt;/goals&gt;</span><br><span class="line">                        &lt;!-- 绑定的阶段 --&gt;</span><br><span class="line">                        &lt;phase&gt;verify&lt;/phase&gt;</span><br><span class="line">                    &lt;/execution&gt;</span><br><span class="line">                &lt;/executions&gt;</span><br><span class="line">            &lt;/plugin&gt;</span><br><span class="line">        &lt;/plugins&gt;</span><br><span class="line">    &lt;/build&gt;</span><br><span class="line"> </span><br><span class="line">&lt;/project&gt;</span><br></pre></td></tr></table></figure><p>运行下面命令：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn install</span><br></pre></td></tr></table></figure><p>效果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn install</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat06 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ maven-chat06 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-chat06 ---</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ maven-chat06 ---</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-source-plugin:3.2.0:jar-no-fork (attach-source) @ maven-chat06 ---</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-install-plugin:2.4:install (default-install) @ maven-chat06 ---</span><br><span class="line">[INFO] Installing D:\code\IdeaProjects\maven-chat06\target\maven-chat06-1.0-SNAPSHOT.jar to C:\Users\Think\.m2\repository\com\javacode2018\maven-chat06\1.0-SNAPSHOT\maven-chat06-1.0-SNAPSHOT.jar</span><br><span class="line">[INFO] Installing D:\code\IdeaProjects\maven-chat06\pom.xml to C:\Users\Think\.m2\repository\com\javacode2018\maven-chat06\1.0-SNAPSHOT\maven-chat06-1.0-SNAPSHOT.pom</span><br><span class="line">[INFO] Installing D:\code\IdeaProjects\maven-chat06\target\maven-chat06-1.0-SNAPSHOT-sources.jar to C:\Users\Think\.m2\repository\com\javacode2018\maven-chat06\1.0-SNAPSHOT\maven-chat06-1.0-SNAPSHOT-sources.jar</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  2.268 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T16:59:12+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>上面有个输出如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">maven-source-plugin:3.2.0:jar-no-fork (attach-source) @ maven-chat06 ---</span><br></pre></td></tr></table></figure><p>可以看出调用了我们配置的插件生成源码jar，上面的括号中的<code>attach-source</code>就是<code>pom.xml</code>中配置的任务id。</p><p>最后有个输出：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[INFO] Installing D:\code\IdeaProjects\maven-chat06\target\maven-chat06-1.0-SNAPSHOT-sources.jar to C:\Users\Think\.m2\repository\com\javacode2018\maven-chat06\1.0-SNAPSHOT\maven-chat06-1.0-SNAPSHOT-sources.jar</span><br></pre></td></tr></table></figure><p>可以看到将源码安装到本地仓库了。</p><p>有些插件的目标默认会绑定到一些生命周期的阶段中，那么如果刚好插件默认绑定的阶段和上面配置的一致，那么上面<code>phase</code>元素可以不写了，那么怎么查看插件的默认绑定呢？</p><figure class="highlight plain"><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">mvn help:describe -Dplugin=插件goupId:插件artifactId[:插件version] -Dgoal=目标名称 -Ddetail</span><br><span class="line">mvn help:describe -Dplugin=插件前缀 -Dgoal=目标名称 -Ddetail</span><br></pre></td></tr></table></figure><p>我们看一下插件<code>source</code>的<code>jar-no-fork</code>目标默认的绑定：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn help:describe -Dplugin=source -Dgoal=jar-no-fork -Ddetail</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-help-plugin:3.2.0:describe (default-cli) @ maven-chat06 ---</span><br><span class="line">[INFO] Mojo: &apos;source:jar-no-fork&apos;</span><br><span class="line">source:jar-no-fork</span><br><span class="line">  Description: This goal bundles all the sources into a jar archive. This</span><br><span class="line">    goal functions the same as the jar goal but does not fork the build and is</span><br><span class="line">    suitable for attaching to the build lifecycle.</span><br><span class="line">  Implementation: org.apache.maven.plugins.source.SourceJarNoForkMojo</span><br><span class="line">  Language: java</span><br><span class="line">  Bound to phase: package</span><br></pre></td></tr></table></figure><p>上面输出中有个<code>Bound to phase: package</code>，表示默认绑定在了<code>package</code>阶段上。</p><p>我们知道3套生命周期的运行时没有依赖的，但是每套中的阶段是有先后顺序的，运行某个阶段的时候，会先执行他前面所有的阶段。清理代码使用的是<code>clean</code>周期中的<code>clean</code>阶段，编译代码用的是<code>default</code>周期中的<code>compile</code>阶段，当直接运行<code>mvn compile</code>编译代码的时候并不会去清理代码，编译代码的时候若发现文件没有变动，会跳过没有变化的文件进行编译。如果我们想每次编译之前强制先清理代码，我们经常这么写：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn clean compile</span><br></pre></td></tr></table></figure><p>上面的写法是不是很熟悉，运行一下看看效果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn clean compile</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-chat06 ---</span><br><span class="line">[INFO] Deleting D:\code\IdeaProjects\maven-chat06\target</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat06 ---</span><br><span class="line">[INFO] Changes detected - recompiling the module!</span><br><span class="line">[INFO] Compiling 1 source file to D:\code\IdeaProjects\maven-chat06\target\classes</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  1.666 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T17:16:53+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>还有其他方式么？</p><p>我们刚才学了自定义绑定，我们可以在<code>default</code>生命周期的第一个阶段<code>validate</code>绑定清理代码的插件，那我们来通过自定义绑定来实现一下，<code>project-&gt;build-&gt;plugins</code>元素中加入下面配置：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">&lt;plugin&gt;</span><br><span class="line">    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;maven-clean-plugin&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;2.5&lt;/version&gt;</span><br><span class="line">    &lt;executions&gt;</span><br><span class="line">        &lt;!-- 使用插件需要执行的任务 --&gt;</span><br><span class="line">        &lt;execution&gt;</span><br><span class="line">            &lt;!-- 任务中插件的目标，可以指定多个 --&gt;</span><br><span class="line">            &lt;id&gt;clean-target&lt;/id&gt;</span><br><span class="line">            &lt;goals&gt;</span><br><span class="line">                &lt;goal&gt;clean&lt;/goal&gt;</span><br><span class="line">            &lt;/goals&gt;</span><br><span class="line">            &lt;!-- 绑定的阶段 --&gt;</span><br><span class="line">            &lt;phase&gt;validate&lt;/phase&gt;</span><br><span class="line">        &lt;/execution&gt;</span><br><span class="line">    &lt;/executions&gt;</span><br><span class="line">&lt;/plugin&gt;</span><br></pre></td></tr></table></figure><p>运行下面命令看效果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn compile</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-clean-plugin:2.5:clean (clean-target) @ maven-chat06 ---</span><br><span class="line">[INFO] Deleting D:\code\IdeaProjects\maven-chat06\target</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat06 ---</span><br><span class="line">[INFO] Changes detected - recompiling the module!</span><br><span class="line">[INFO] Compiling 1 source file to D:\code\IdeaProjects\maven-chat06\target\classes</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  1.630 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T17:22:37+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>输出中有：</p><figure class="highlight plain"><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">[INFO] --- maven-clean-plugin:2.5:clean (clean-target) @ maven-chat06 ---</span><br><span class="line">[INFO] Deleting D:\code\IdeaProjects\maven-chat06\target</span><br></pre></td></tr></table></figure><p>这个表示运行了代码清理的功能，进行了代码清理，是不是感觉很爽，不用每次都写<code>clean</code>了。</p><h2 id="POM-xml插件配置详解"><a href="#POM-xml插件配置详解" class="headerlink" title="POM.xml插件配置详解"></a>POM.xml插件配置详解</h2><h3 id="插件目标共享参数配置"><a href="#插件目标共享参数配置" class="headerlink" title="插件目标共享参数配置"></a>插件目标共享参数配置</h3><p><code>build-&gt;plugins-&gt;plugin</code>中配置：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 插件参数配置，对插件中所有的目标起效 --&gt;</span><br><span class="line">&lt;configuration&gt;</span><br><span class="line">    &lt;目标参数名&gt;参数值&lt;/目标参数名&gt;</span><br><span class="line">&lt;/configuration&gt;</span><br></pre></td></tr></table></figure><blockquote><p><code>configuration</code>节点下配置目标参数的值，节点名称为目标的参数名称，上面这种配置对当前插件的所有目标起效，也就是说这个插件中所有的目标共享此参数配置。</p></blockquote><p>案例：</p><blockquote><p>将案例中的pom.xml中的build元素修改成下面这样。</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&lt;build&gt;</span><br><span class="line">    &lt;plugins&gt;</span><br><span class="line">        &lt;plugin&gt;</span><br><span class="line">            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;2.12.4&lt;/version&gt;</span><br><span class="line">            &lt;!-- 插件参数配置，对插件中所有的目标起效 --&gt;</span><br><span class="line">            &lt;configuration&gt;</span><br><span class="line">                &lt;skip&gt;true&lt;/skip&gt;</span><br><span class="line">            &lt;/configuration&gt;</span><br><span class="line">        &lt;/plugin&gt;</span><br><span class="line">    &lt;/plugins&gt;</span><br><span class="line">&lt;/build&gt;</span><br></pre></td></tr></table></figure><p>运行下面命令，看效果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn test</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat06 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ maven-chat06 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-chat06 ---</span><br><span class="line">[INFO] Tests are skipped.</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  1.328 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T17:30:58+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>可以看到<code>Test are skipped</code>，说明跳过了测试，到此为止，跳过测试已经讲了3种了：</p><blockquote><ol><li>mvn -Dmaven.test.skip=tue</li><li>properties中配置&lt;maven.test.skip&gt;true&lt;/maven.test.skip&gt;</li><li>build中配置插件参数的方式</li></ol></blockquote><p>上面这个配置参数方式对当前插件的所有目标有效，如果想对指定的目标进行配置呢，用下面的方式。</p><h3 id="插件目标参数配置"><a href="#插件目标参数配置" class="headerlink" title="插件目标参数配置"></a>插件目标参数配置</h3><p><code>project-&gt;build-&gt;plugins-&gt;plugin-&gt;executions-&gt;execution</code>元素中进行配置，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- 这个地方配置只对当前任务有效 --&gt;</span><br><span class="line">&lt;configuration&gt;</span><br><span class="line">    &lt;目标参数名&gt;参数值&lt;/目标参数名&gt;</span><br><span class="line">&lt;/configuration&gt;</span><br></pre></td></tr></table></figure><blockquote><p>上面这种配置常用于自定义插件绑定，只对当前任务有效。</p></blockquote><p>感受一下效果，将pom.xml中的build元素改为下面内容：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&lt;build&gt;</span><br><span class="line">    &lt;plugins&gt;</span><br><span class="line">        &lt;plugin&gt;</span><br><span class="line">            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;2.12.4&lt;/version&gt;</span><br><span class="line">            &lt;executions&gt;</span><br><span class="line">                &lt;execution&gt;</span><br><span class="line">                    &lt;goals&gt;</span><br><span class="line">                        &lt;goal&gt;test&lt;/goal&gt;</span><br><span class="line">                        &lt;goal&gt;help&lt;/goal&gt;</span><br><span class="line">                    &lt;/goals&gt;</span><br><span class="line">                    &lt;phase&gt;pre-clean&lt;/phase&gt;</span><br><span class="line">                    &lt;!-- 这个地方配置只对当前任务有效 --&gt;</span><br><span class="line">                    &lt;configuration&gt;</span><br><span class="line">                        &lt;skip&gt;true&lt;/skip&gt;</span><br><span class="line">                    &lt;/configuration&gt;</span><br><span class="line">                &lt;/execution&gt;</span><br><span class="line">            &lt;/executions&gt;</span><br><span class="line">        &lt;/plugin&gt;</span><br><span class="line">    &lt;/plugins&gt;</span><br><span class="line">&lt;/build&gt;</span><br></pre></td></tr></table></figure><blockquote><p>上面自定义了一个绑定，在clean周期的<code>pre-clean</code>阶段绑定了插件<code>maven-surefire-plugin</code>的两个目标<code>test和help</code>，<code>execution</code>元素没有指定<code>id</code>，所以默认id是<code>default</code>。</p></blockquote><p>运行下面命令，见效果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><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">D:\code\IdeaProjects\maven-chat06&gt;mvn pre-clean</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:test (default) @ maven-chat06 ---</span><br><span class="line">[INFO] Tests are skipped.</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:help (default) @ maven-chat06 ---</span><br><span class="line">[INFO] Maven Surefire Plugin 2.12.4</span><br><span class="line">  Surefire is a test framework project.</span><br><span class="line"> </span><br><span class="line">This plugin has 2 goals:</span><br><span class="line"> </span><br><span class="line">surefire:help</span><br><span class="line">  Display help information on maven-surefire-plugin.</span><br><span class="line">  Call mvn surefire:help -Ddetail=true -Dgoal=&lt;goal-name&gt; to display parameter</span><br><span class="line">  details.</span><br><span class="line"> </span><br><span class="line">surefire:test</span><br><span class="line">  Run tests using Surefire.</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  0.738 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T17:41:08+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><blockquote><p>可以看到上面输出中运行了插件的两个目标，和预期结果一致。</p></blockquote><h2 id="maven插件信息"><a href="#maven插件信息" class="headerlink" title="maven插件信息"></a>maven插件信息</h2><p>上面我们介绍了，可以通过下面命令获取插件详细介绍信息</p><figure class="highlight plain"><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">mvn help:describe -Dplugin=插件goupId:插件artifactId[:插件version] -Dgoal=目标名称 -Ddetail</span><br><span class="line">mvn help:describe -Dplugin=插件前缀 -Dgoal=目标名称 -Ddetail</span><br></pre></td></tr></table></figure><p>更多maven插件的帮助文档可以参考maven的官方网站，上面有详细的介绍，建议大家去看看，地址：<code>http://maven.apache.org/plugins/</code></p><h2 id="插件解析机制"><a href="#插件解析机制" class="headerlink" title="插件解析机制"></a>插件解析机制</h2><p>为了方便用户使用和配置插件，maven不需要用户提供完整的插件坐标信息，就可以解析到正确的插件，不过我建议使用插件配置的时候最好还是配置完整的坐标信息，不然不利于新人的理解和问题的排查。</p><h3 id="插件仓库"><a href="#插件仓库" class="headerlink" title="插件仓库"></a>插件仓库</h3><p>与其他maven构件一样，插件构件也是基于坐标存储在maven仓库中，有需要的时候，maven会从本地查找插件，如果不存在，则到远程仓库查找，找到了以后下载到本地仓库，然后使用。</p><p>大家回忆一下，上一章讲过的，pom.xml中可以配置依赖的构件的仓库地址，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&lt;repositories&gt;</span><br><span class="line">    &lt;repository&gt;</span><br><span class="line">        &lt;id&gt;maven-nexus&lt;/id&gt;</span><br><span class="line">        &lt;url&gt;http://localhost:8081/repository/maven-public/&lt;/url&gt;</span><br><span class="line">        &lt;releases&gt;</span><br><span class="line">            &lt;enabled&gt;true&lt;/enabled&gt;</span><br><span class="line">        &lt;/releases&gt;</span><br><span class="line">        &lt;snapshots&gt;</span><br><span class="line">            &lt;enabled&gt;true&lt;/enabled&gt;</span><br><span class="line">        &lt;/snapshots&gt;</span><br><span class="line">    &lt;/repository&gt;</span><br><span class="line">&lt;/repositories&gt;</span><br></pre></td></tr></table></figure><p>但是插件仓库的配置和这个有一点不一样，插件的是在<code>pluginRepositories-&gt;pluginRepository</code>元素中配置的，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&lt;pluginRepositories&gt;</span><br><span class="line">    &lt;pluginRepository&gt;</span><br><span class="line">        &lt;id&gt;myplugin-repository&lt;/id&gt;</span><br><span class="line">        &lt;url&gt;http://repo1.maven.org/maven2/&lt;/url&gt;</span><br><span class="line">        &lt;releases&gt;</span><br><span class="line">            &lt;enabled&gt;true&lt;/enabled&gt;</span><br><span class="line">        &lt;/releases&gt;</span><br><span class="line">    &lt;/pluginRepository&gt;</span><br><span class="line">&lt;/pluginRepositories&gt;</span><br></pre></td></tr></table></figure><p>看一下上面2段配置，<code>repository</code>中的配置和<code>pluginRepository</code>中的子元素是一样的，这个主意下就可以了。</p><h3 id="插件的默认groupId"><a href="#插件的默认groupId" class="headerlink" title="插件的默认groupId"></a>插件的默认groupId</h3><p>在pom.xml中配置插件的时候，如果是官方的插件，可以省略<code>groupId</code>。</p><p>案例：</p><p>修改本篇示例中的pom.xml，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><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">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="line">&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;</span><br><span class="line">         xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span><br><span class="line">         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;</span><br><span class="line">    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;groupId&gt;com.javacode2018&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;maven-chat06&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;</span><br><span class="line">    &lt;packaging&gt;jar&lt;/packaging&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;properties&gt;</span><br><span class="line">        &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;</span><br><span class="line">    &lt;/properties&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;build&gt;</span><br><span class="line">        &lt;plugins&gt;</span><br><span class="line">            &lt;plugin&gt;</span><br><span class="line">                &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;</span><br><span class="line">                &lt;version&gt;3.1&lt;/version&gt;</span><br><span class="line">                &lt;configuration&gt;</span><br><span class="line">                    &lt;compilerVersion&gt;1.8&lt;/compilerVersion&gt;</span><br><span class="line">                    &lt;source&gt;1.8&lt;/source&gt;</span><br><span class="line">                    &lt;target&gt;1.8&lt;/target&gt;</span><br><span class="line">                &lt;/configuration&gt;</span><br><span class="line">            &lt;/plugin&gt;</span><br><span class="line">        &lt;/plugins&gt;</span><br><span class="line">    &lt;/build&gt;</span><br><span class="line"> </span><br><span class="line">&lt;/project&gt;</span><br></pre></td></tr></table></figure><blockquote><p>上面用到了<code>maven-compiler-plugin</code>，这个插件是编译代码的，是maven官方提供的插件，我们省略了<code>groupId</code>。</p><p>上面这个插件用于编译代码的，编译代码的时候需要指定编译器的版本，源码的版本，目标代码的版本，都是用的是1.8。</p><p>大家回头去看一下，文章最开始的时候，在<code>properties</code>中有几个属性值是1.8的配置，这几个值默认会被<code>maven-compiler-plugin</code>这个插件的上面3个参数获取，具体可以去看一下这个插件<code>compile</code>目标的参数说明。</p></blockquote><p>运行下面命令：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn clean compile</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat06 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat06 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-chat06 ---</span><br><span class="line">[INFO] Deleting D:\code\IdeaProjects\maven-chat06\target</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat06 ---</span><br><span class="line">[INFO] Using &apos;UTF-8&apos; encoding to copy filtered resources.</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat06 ---</span><br><span class="line">[INFO] Changes detected - recompiling the module!</span><br><span class="line">[INFO] Compiling 1 source file to D:\code\IdeaProjects\maven-chat06\target\classes</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  1.692 s</span><br><span class="line">[INFO] Finished at: 2019-11-18T18:11:34+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><blockquote><p>可以看到可以正常运行。</p></blockquote><p>上面pom.xml省略了插件的groupId配置，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br></pre></td></tr></table></figure><p>maven在解析该插件的时候，会自动给这个插件补上默认的官方的groupId，所以可以正常运行，但是不建议大家这么使用，容易让新手比较懵逼。</p><h3 id="插件前缀的解析"><a href="#插件前缀的解析" class="headerlink" title="插件前缀的解析"></a>插件前缀的解析</h3><p>前面说过了使用mvn命令调用插件的时候，可以使用插件的前缀来代替繁琐的插件坐标的方式，那么maven是如何根据插件的前缀找到对应的插件的呢？</p><p>插件前缀与插件groupId:artifactId是一一对应的关系，这个关系的配置存储在仓库的元数据中，元数据位于下面2个xml中：</p><figure class="highlight plain"><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">~/.m2/repository/org/apache/maven/plugins/maven-metadata-central.xml</span><br><span class="line">~/.m2/repository/org/codehaus/mojo/maven-metadata-central.xml</span><br></pre></td></tr></table></figure><p>接几个图，大家感受一下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/559971dd0a6d94a7c0bc928647ebdd5a.png" alt title>                </div>                <div class="image-caption"></div>            </figure><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/8afdf449ee2554b75681ae76910c690b.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>也可以通过在<code>settings.xml</code>中配置，让maven检查其他grouId上的插件元数据中前缀和插件关系的配置，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;settings&gt;</span><br><span class="line">  &lt;pluginGroups&gt;</span><br><span class="line">    &lt;pluginGroup&gt;com.your.plugins&lt;/pluginGroup&gt;</span><br><span class="line">  &lt;/pluginGroups&gt;</span><br><span class="line">&lt;/settings&gt;</span><br></pre></td></tr></table></figure><blockquote><p>pluginGroups中有多个pluginGroup，可以配置你自己插件的元数据所在的groupId，然后可以通过前缀来访问你自己的插件元数据目录，此处先不细说，这个后面文章中讲自定义插件的时候会再次说明。</p></blockquote><h2 id="查看项目最终pom-xml文件"><a href="#查看项目最终pom-xml文件" class="headerlink" title="查看项目最终pom.xml文件"></a>查看项目最终pom.xml文件</h2><p>我们的pom.xml默认会继承maven顶级的一个父类pom.xml，顶级的pom.xml中指定了很多默认的配置，如生命周期中的阶段和很多插件的绑定，这些如果我们想看到，到哪里看呢？</p><p><code>mvn</code>命令在项目中执行的时候，我们的pom.xml和父类的pom.xml最终会进行合并，当我们的pom.xml写的比较复杂的时候，最终合并之后是什么效果呢，我们可以通过下面这个命令查看：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn help:effective-pom</span><br></pre></td></tr></table></figure><p>效果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat06&gt;mvn help:effective-pom &gt; 1.xml</span><br></pre></td></tr></table></figure><p>上面我们将命令产生的结果输出到项目的1.xml文件中了，我们看一下项目的1.xml的内容：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version=&quot;1.0&quot; encoding=&quot;GBK&quot;?&gt;</span><br><span class="line">&lt;!-- ====================================================================== --&gt;</span><br><span class="line">&lt;!--                                                                        --&gt;</span><br><span class="line">&lt;!-- Generated by Maven Help Plugin on 2019-11-18T18:41:40+08:00            --&gt;</span><br><span class="line">&lt;!-- See: http://maven.apache.org/plugins/maven-help-plugin/                --&gt;</span><br><span class="line">&lt;!--                                                                        --&gt;</span><br><span class="line">&lt;!-- ====================================================================== --&gt;</span><br><span class="line">&lt;!-- ====================================================================== --&gt;</span><br><span class="line">&lt;!--                                                                        --&gt;</span><br><span class="line">&lt;!-- Effective POM for project                                              --&gt;</span><br><span class="line">&lt;!-- &apos;com.javacode2018:maven-chat06:jar:1.0-SNAPSHOT&apos;                       --&gt;</span><br><span class="line">&lt;!--                                                                        --&gt;</span><br><span class="line">&lt;!-- ====================================================================== --&gt;</span><br><span class="line">&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span><br><span class="line">         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;</span><br><span class="line">    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;</span><br><span class="line">    &lt;groupId&gt;com.javacode2018&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;maven-chat06&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;</span><br><span class="line">    &lt;properties&gt;</span><br><span class="line">        &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;</span><br><span class="line">    &lt;/properties&gt;</span><br><span class="line">    &lt;repositories&gt;</span><br><span class="line">        &lt;repository&gt;</span><br><span class="line">            &lt;snapshots&gt;</span><br><span class="line">                &lt;enabled&gt;false&lt;/enabled&gt;</span><br><span class="line">            &lt;/snapshots&gt;</span><br><span class="line">            &lt;id&gt;central&lt;/id&gt;</span><br><span class="line">            &lt;name&gt;Central Repository&lt;/name&gt;</span><br><span class="line">            &lt;url&gt;https://repo.maven.apache.org/maven2&lt;/url&gt;</span><br><span class="line">        &lt;/repository&gt;</span><br><span class="line">    &lt;/repositories&gt;</span><br><span class="line">    &lt;pluginRepositories&gt;</span><br><span class="line">        &lt;pluginRepository&gt;</span><br><span class="line">            &lt;releases&gt;</span><br><span class="line">                &lt;updatePolicy&gt;never&lt;/updatePolicy&gt;</span><br><span class="line">            &lt;/releases&gt;</span><br><span class="line">            &lt;snapshots&gt;</span><br><span class="line">                &lt;enabled&gt;false&lt;/enabled&gt;</span><br><span class="line">            &lt;/snapshots&gt;</span><br><span class="line">            &lt;id&gt;central&lt;/id&gt;</span><br><span class="line">            &lt;name&gt;Central Repository&lt;/name&gt;</span><br><span class="line">            &lt;url&gt;https://repo.maven.apache.org/maven2&lt;/url&gt;</span><br><span class="line">        &lt;/pluginRepository&gt;</span><br><span class="line">    &lt;/pluginRepositories&gt;</span><br><span class="line">    &lt;build&gt;</span><br><span class="line">        &lt;sourceDirectory&gt;D:\code\IdeaProjects\maven-chat06\src\main\java&lt;/sourceDirectory&gt;</span><br><span class="line">        &lt;scriptSourceDirectory&gt;D:\code\IdeaProjects\maven-chat06\src\main\scripts&lt;/scriptSourceDirectory&gt;</span><br><span class="line">        &lt;testSourceDirectory&gt;D:\code\IdeaProjects\maven-chat06\src\test\java&lt;/testSourceDirectory&gt;</span><br><span class="line">        &lt;outputDirectory&gt;D:\code\IdeaProjects\maven-chat06\target\classes&lt;/outputDirectory&gt;</span><br><span class="line">        &lt;testOutputDirectory&gt;D:\code\IdeaProjects\maven-chat06\target\test-classes&lt;/testOutputDirectory&gt;</span><br><span class="line">        &lt;resources&gt;</span><br><span class="line">            &lt;resource&gt;</span><br><span class="line">                &lt;directory&gt;D:\code\IdeaProjects\maven-chat06\src\main\resources&lt;/directory&gt;</span><br><span class="line">            &lt;/resource&gt;</span><br><span class="line">        &lt;/resources&gt;</span><br><span class="line">        &lt;testResources&gt;</span><br><span class="line">            &lt;testResource&gt;</span><br><span class="line">                &lt;directory&gt;D:\code\IdeaProjects\maven-chat06\src\test\resources&lt;/directory&gt;</span><br><span class="line">            &lt;/testResource&gt;</span><br><span class="line">        &lt;/testResources&gt;</span><br><span class="line">        &lt;directory&gt;D:\code\IdeaProjects\maven-chat06\target&lt;/directory&gt;</span><br><span class="line">        &lt;finalName&gt;maven-chat06-1.0-SNAPSHOT&lt;/finalName&gt;</span><br><span class="line">        &lt;pluginManagement&gt;</span><br><span class="line">            &lt;plugins&gt;</span><br><span class="line">                &lt;plugin&gt;</span><br><span class="line">                    &lt;artifactId&gt;maven-antrun-plugin&lt;/artifactId&gt;</span><br><span class="line">                    &lt;version&gt;1.3&lt;/version&gt;</span><br><span class="line">                &lt;/plugin&gt;</span><br><span class="line">                &lt;plugin&gt;</span><br><span class="line">                    &lt;artifactId&gt;maven-assembly-plugin&lt;/artifactId&gt;</span><br><span class="line">                    &lt;version&gt;2.2-beta-5&lt;/version&gt;</span><br><span class="line">                &lt;/plugin&gt;</span><br><span class="line">                &lt;plugin&gt;</span><br><span class="line">                    &lt;artifactId&gt;maven-dependency-plugin&lt;/artifactId&gt;</span><br><span class="line">                    &lt;version&gt;2.8&lt;/version&gt;</span><br><span class="line">                &lt;/plugin&gt;</span><br><span class="line">                &lt;plugin&gt;</span><br><span class="line">                    &lt;artifactId&gt;maven-release-plugin&lt;/artifactId&gt;</span><br><span class="line">                    &lt;version&gt;2.5.3&lt;/version&gt;</span><br><span class="line">                &lt;/plugin&gt;</span><br><span class="line">            &lt;/plugins&gt;</span><br><span class="line">        &lt;/pluginManagement&gt;</span><br><span class="line">        &lt;plugins&gt;</span><br><span class="line">            &lt;plugin&gt;</span><br><span class="line">                &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;</span><br><span class="line">                &lt;version&gt;3.1&lt;/version&gt;</span><br><span class="line">                &lt;executions&gt;</span><br><span class="line">                    &lt;execution&gt;</span><br><span class="line">                        &lt;id&gt;default-compile&lt;/id&gt;</span><br><span class="line">                        &lt;phase&gt;compile&lt;/phase&gt;</span><br><span class="line">                        &lt;goals&gt;</span><br><span class="line">                            &lt;goal&gt;compile&lt;/goal&gt;</span><br><span class="line">                        &lt;/goals&gt;</span><br><span class="line">                        &lt;configuration&gt;</span><br><span class="line">                            &lt;compilerVersion&gt;1.8&lt;/compilerVersion&gt;</span><br><span class="line">                            &lt;source&gt;1.8&lt;/source&gt;</span><br><span class="line">                            &lt;target&gt;1.8&lt;/target&gt;</span><br><span class="line">                        &lt;/configuration&gt;</span><br><span class="line">                    &lt;/execution&gt;</span><br><span class="line">                    &lt;execution&gt;</span><br><span class="line">                        &lt;id&gt;default-testCompile&lt;/id&gt;</span><br><span class="line">                        &lt;phase&gt;test-compile&lt;/phase&gt;</span><br><span class="line">                        &lt;goals&gt;</span><br><span class="line">                            &lt;goal&gt;testCompile&lt;/goal&gt;</span><br><span class="line">                        &lt;/goals&gt;</span><br><span class="line">                        &lt;configuration&gt;</span><br><span class="line">                            &lt;compilerVersion&gt;1.8&lt;/compilerVersion&gt;</span><br><span class="line">                            &lt;source&gt;1.8&lt;/source&gt;</span><br><span class="line">                            &lt;target&gt;1.8&lt;/target&gt;</span><br><span class="line">                        &lt;/configuration&gt;</span><br><span class="line">                    &lt;/execution&gt;</span><br><span class="line">                &lt;/executions&gt;</span><br><span class="line">                &lt;configuration&gt;</span><br><span class="line">                    &lt;compilerVersion&gt;1.8&lt;/compilerVersion&gt;</span><br><span class="line">                    &lt;source&gt;1.8&lt;/source&gt;</span><br><span class="line">                    &lt;target&gt;1.8&lt;/target&gt;</span><br><span class="line">                &lt;/configuration&gt;</span><br><span class="line">            &lt;/plugin&gt;</span><br><span class="line">            &lt;plugin&gt;</span><br><span class="line">                &lt;artifactId&gt;maven-clean-plugin&lt;/artifactId&gt;</span><br><span class="line">                &lt;version&gt;2.5&lt;/version&gt;</span><br><span class="line">                &lt;executions&gt;</span><br><span class="line">                    &lt;execution&gt;</span><br><span class="line">                        &lt;id&gt;default-clean&lt;/id&gt;</span><br><span class="line">                        &lt;phase&gt;clean&lt;/phase&gt;</span><br><span class="line">                        &lt;goals&gt;</span><br><span class="line">                            &lt;goal&gt;clean&lt;/goal&gt;</span><br><span class="line">                        &lt;/goals&gt;</span><br><span class="line">                    &lt;/execution&gt;</span><br><span class="line">                &lt;/executions&gt;</span><br><span class="line">            &lt;/plugin&gt;</span><br><span class="line">            &lt;plugin&gt;</span><br><span class="line">                &lt;artifactId&gt;maven-resources-plugin&lt;/artifactId&gt;</span><br><span class="line">                &lt;version&gt;2.6&lt;/version&gt;</span><br><span class="line">                &lt;executions&gt;</span><br><span class="line">                    &lt;execution&gt;</span><br><span class="line">                        &lt;id&gt;default-testResources&lt;/id&gt;</span><br><span class="line">                        &lt;phase&gt;process-test-resources&lt;/phase&gt;</span><br><span class="line">                        &lt;goals&gt;</span><br><span class="line">                            &lt;goal&gt;testResources&lt;/goal&gt;</span><br><span class="line">                        &lt;/goals&gt;</span><br><span class="line">                    &lt;/execution&gt;</span><br><span class="line">                    &lt;execution&gt;</span><br><span class="line">                        &lt;id&gt;default-resources&lt;/id&gt;</span><br><span class="line">                        &lt;phase&gt;process-resources&lt;/phase&gt;</span><br><span class="line">                        &lt;goals&gt;</span><br><span class="line">                            &lt;goal&gt;resources&lt;/goal&gt;</span><br><span class="line">                        &lt;/goals&gt;</span><br><span class="line">                    &lt;/execution&gt;</span><br><span class="line">                &lt;/executions&gt;</span><br><span class="line">            &lt;/plugin&gt;</span><br><span class="line">            &lt;plugin&gt;</span><br><span class="line">                &lt;artifactId&gt;maven-jar-plugin&lt;/artifactId&gt;</span><br><span class="line">                &lt;version&gt;2.4&lt;/version&gt;</span><br><span class="line">                &lt;executions&gt;</span><br><span class="line">                    &lt;execution&gt;</span><br><span class="line">                        &lt;id&gt;default-jar&lt;/id&gt;</span><br><span class="line">                        &lt;phase&gt;package&lt;/phase&gt;</span><br><span class="line">                        &lt;goals&gt;</span><br><span class="line">                            &lt;goal&gt;jar&lt;/goal&gt;</span><br><span class="line">                        &lt;/goals&gt;</span><br><span class="line">                    &lt;/execution&gt;</span><br><span class="line">                &lt;/executions&gt;</span><br><span class="line">            &lt;/plugin&gt;</span><br><span class="line">            &lt;plugin&gt;</span><br><span class="line">                &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;</span><br><span class="line">                &lt;version&gt;2.12.4&lt;/version&gt;</span><br><span class="line">                &lt;executions&gt;</span><br><span class="line">                    &lt;execution&gt;</span><br><span class="line">                        &lt;id&gt;default-test&lt;/id&gt;</span><br><span class="line">                        &lt;phase&gt;test&lt;/phase&gt;</span><br><span class="line">                        &lt;goals&gt;</span><br><span class="line">                            &lt;goal&gt;test&lt;/goal&gt;</span><br><span class="line">                        &lt;/goals&gt;</span><br><span class="line">                    &lt;/execution&gt;</span><br><span class="line">                &lt;/executions&gt;</span><br><span class="line">            &lt;/plugin&gt;</span><br><span class="line">            &lt;plugin&gt;</span><br><span class="line">                &lt;artifactId&gt;maven-install-plugin&lt;/artifactId&gt;</span><br><span class="line">                &lt;version&gt;2.4&lt;/version&gt;</span><br><span class="line">                &lt;executions&gt;</span><br><span class="line">                    &lt;execution&gt;</span><br><span class="line">                        &lt;id&gt;default-install&lt;/id&gt;</span><br><span class="line">                        &lt;phase&gt;install&lt;/phase&gt;</span><br><span class="line">                        &lt;goals&gt;</span><br><span class="line">                            &lt;goal&gt;install&lt;/goal&gt;</span><br><span class="line">                        &lt;/goals&gt;</span><br><span class="line">                    &lt;/execution&gt;</span><br><span class="line">                &lt;/executions&gt;</span><br><span class="line">            &lt;/plugin&gt;</span><br><span class="line">            &lt;plugin&gt;</span><br><span class="line">                &lt;artifactId&gt;maven-deploy-plugin&lt;/artifactId&gt;</span><br><span class="line">                &lt;version&gt;2.7&lt;/version&gt;</span><br><span class="line">                &lt;executions&gt;</span><br><span class="line">                    &lt;execution&gt;</span><br><span class="line">                        &lt;id&gt;default-deploy&lt;/id&gt;</span><br><span class="line">                        &lt;phase&gt;deploy&lt;/phase&gt;</span><br><span class="line">                        &lt;goals&gt;</span><br><span class="line">                            &lt;goal&gt;deploy&lt;/goal&gt;</span><br><span class="line">                        &lt;/goals&gt;</span><br><span class="line">                    &lt;/execution&gt;</span><br><span class="line">                &lt;/executions&gt;</span><br><span class="line">            &lt;/plugin&gt;</span><br><span class="line">            &lt;plugin&gt;</span><br><span class="line">                &lt;artifactId&gt;maven-site-plugin&lt;/artifactId&gt;</span><br><span class="line">                &lt;version&gt;3.3&lt;/version&gt;</span><br><span class="line">                &lt;executions&gt;</span><br><span class="line">                    &lt;execution&gt;</span><br><span class="line">                        &lt;id&gt;default-site&lt;/id&gt;</span><br><span class="line">                        &lt;phase&gt;site&lt;/phase&gt;</span><br><span class="line">                        &lt;goals&gt;</span><br><span class="line">                            &lt;goal&gt;site&lt;/goal&gt;</span><br><span class="line">                        &lt;/goals&gt;</span><br><span class="line">                        &lt;configuration&gt;</span><br><span class="line">                            &lt;outputDirectory&gt;D:\code\IdeaProjects\maven-chat06\target\site&lt;/outputDirectory&gt;</span><br><span class="line">                            &lt;reportPlugins&gt;</span><br><span class="line">                                &lt;reportPlugin&gt;</span><br><span class="line">                                    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br><span class="line">                                    &lt;artifactId&gt;maven-project-info-reports-plugin&lt;/artifactId&gt;</span><br><span class="line">                                &lt;/reportPlugin&gt;</span><br><span class="line">                            &lt;/reportPlugins&gt;</span><br><span class="line">                        &lt;/configuration&gt;</span><br><span class="line">                    &lt;/execution&gt;</span><br><span class="line">                    &lt;execution&gt;</span><br><span class="line">                        &lt;id&gt;default-deploy&lt;/id&gt;</span><br><span class="line">                        &lt;phase&gt;site-deploy&lt;/phase&gt;</span><br><span class="line">                        &lt;goals&gt;</span><br><span class="line">                            &lt;goal&gt;deploy&lt;/goal&gt;</span><br><span class="line">                        &lt;/goals&gt;</span><br><span class="line">                        &lt;configuration&gt;</span><br><span class="line">                            &lt;outputDirectory&gt;D:\code\IdeaProjects\maven-chat06\target\site&lt;/outputDirectory&gt;</span><br><span class="line">                            &lt;reportPlugins&gt;</span><br><span class="line">                                &lt;reportPlugin&gt;</span><br><span class="line">                                    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br><span class="line">                                    &lt;artifactId&gt;maven-project-info-reports-plugin&lt;/artifactId&gt;</span><br><span class="line">                                &lt;/reportPlugin&gt;</span><br><span class="line">                            &lt;/reportPlugins&gt;</span><br><span class="line">                        &lt;/configuration&gt;</span><br><span class="line">                    &lt;/execution&gt;</span><br><span class="line">                &lt;/executions&gt;</span><br><span class="line">                &lt;configuration&gt;</span><br><span class="line">                    &lt;outputDirectory&gt;D:\code\IdeaProjects\maven-chat06\target\site&lt;/outputDirectory&gt;</span><br><span class="line">                    &lt;reportPlugins&gt;</span><br><span class="line">                        &lt;reportPlugin&gt;</span><br><span class="line">                            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br><span class="line">                            &lt;artifactId&gt;maven-project-info-reports-plugin&lt;/artifactId&gt;</span><br><span class="line">                        &lt;/reportPlugin&gt;</span><br><span class="line">                    &lt;/reportPlugins&gt;</span><br><span class="line">                &lt;/configuration&gt;</span><br><span class="line">            &lt;/plugin&gt;</span><br><span class="line">        &lt;/plugins&gt;</span><br><span class="line">    &lt;/build&gt;</span><br><span class="line">    &lt;reporting&gt;</span><br><span class="line">        &lt;outputDirectory&gt;D:\code\IdeaProjects\maven-chat06\target\site&lt;/outputDirectory&gt;</span><br><span class="line">    &lt;/reporting&gt;</span><br><span class="line">&lt;/project&gt;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;用户属性Properties的使用&quot;&gt;&lt;a href=&quot;#用户属性Properties的使用&quot; class=&quot;headerlink&quot; title=&quot;用户属性Properties的使用&quot;&gt;&lt;/a&gt;用户属性Properties的使用&lt;/h1&gt;&lt;p&gt;项目pom.xml中
      
    
    </summary>
    
      <category term="maven" scheme="https://www.caozhg.com/categories/maven/"/>
    
    
      <category term="maven" scheme="https://www.caozhg.com/tags/maven/"/>
    
  </entry>
  
  <entry>
    <title>Maven 私服详解</title>
    <link href="https://www.caozhg.com/2023/02/22/Maven-%E7%A7%81%E6%9C%8D%E8%AF%A6%E8%A7%A3/"/>
    <id>https://www.caozhg.com/2023/02/22/Maven-私服详解/</id>
    <published>2023-02-22T05:39:00.000Z</published>
    <updated>2023-02-22T06:18:22.822Z</updated>
    
    <content type="html"><![CDATA[<h1 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h1><ol><li><p>maven3.6.1</p></li><li><p>开发工具idea</p></li><li><p>jdk1.8</p></li></ol><h1 id="私服介绍"><a href="#私服介绍" class="headerlink" title="私服介绍"></a>私服介绍</h1><p>私服也是远程仓库中的一种，我们为什么需要私服呢？</p><p>如果我们一个团队中有几百个人在开发一些项目，都是采用maven的方式来组织项目，那么我们每个人都需要从远程仓库中把需要依赖的构件下载到本地仓库，这对公司的网络要求也比较高，为了节省这个宽带和加快下载速度，我们在公司内部局域网内部可以架设一台服务器，这台服务器起到一个代理的作用，公司里面的所有开发者去访问这个服务器，这台服务器将需要的构件返回给我们，如果这台服务器中也没有我们需要的构件，那么这个代理服务器会去远程仓库中查找，然后将其先下载到代理服务器中，然后再返回给开发者本地的仓库。</p><p>还有公司内部有很多项目之间会相互依赖，你可能是架构组的，你需要开发一些jar包给其他组使用，此时，我们可以将自己jar发布到私服中给其他同事使用，如果没有私服，可能需要我们手动发给别人或者上传到共享机器中，不过管理起来不是很方便。</p><p><strong>总体上来说私服有以下好处：</strong></p><ol><li><p>加速maven构件的下载速度</p></li><li><p>节省宽带，加速项目构建速度</p></li><li><p>方便部署自己的构件以供他人使用</p></li><li><p>提高maven的稳定性，中央仓库需要本机能够访问外网，而如果采用私服的方式，只需要本机可以访问内网私服就可以了</p></li></ol><p>有3种专门的maven仓库管理软件可以用来帮助我们搭建私服：</p><ol><li><p>Apache基金会的archiva</p><blockquote><p><a href="http://archiva.apache.org/" target="_blank" rel="noopener">http://archiva.apache.org/</a></p></blockquote></li><li><p>JFrog的Artifactory</p><blockquote><p><a href="https://jfrog.com/artifactory/" target="_blank" rel="noopener">https://jfrog.com/artifactory/</a></p></blockquote></li><li><p>Sonatype的Nexus</p><blockquote><p><a href="https://my.sonatype.com/" target="_blank" rel="noopener">https://my.sonatype.com/</a></p></blockquote></li></ol><p>这些都是开源的私服软件，都可以自由使用。用的最多的是第三种Nexus，本文我们主要以这个来讲解，其他2种有兴趣的朋友可以去研究一下。</p><h1 id="Windows10中安装Nexus私服"><a href="#Windows10中安装Nexus私服" class="headerlink" title="Windows10中安装Nexus私服"></a>Windows10中安装Nexus私服</h1><p>nexus是java开发的，所以运行的时候需要有java环境的支持。</p><h2 id="安装jdk"><a href="#安装jdk" class="headerlink" title="安装jdk"></a>安装jdk</h2><p>windows安装jdk此处不在赘述</p><h2 id="下载nexus"><a href="#下载nexus" class="headerlink" title="下载nexus"></a>下载nexus</h2><blockquote><p><a href="https://help.sonatype.com/repomanager3/download" target="_blank" rel="noopener">https://help.sonatype.com/repomanager3/download</a></p></blockquote><table><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>Unix archive</td><td><a href="https://download.sonatype.com/nexus/3/nexus-3.19.1-01-unix.tar.gz" target="_blank" rel="noopener">https://download.sonatype.com/nexus/3/nexus-3.19.1-01-unix.tar.gz</a> ( ASC , MD5 , SHA1 )</td></tr><tr><td>Windows archive</td><td><a href="https://download.sonatype.com/nexus/3/nexus-3.19.1-01-win64.zip" target="_blank" rel="noopener">https://download.sonatype.com/nexus/3/nexus-3.19.1-01-win64.zip</a> ( ASC , MD5 , SHA1 )</td></tr><tr><td>OSX archive</td><td><a href="https://download.sonatype.com/nexus/3/nexus-3.19.1-01-mac.tgz" target="_blank" rel="noopener">https://download.sonatype.com/nexus/3/nexus-3.19.1-01-mac.tgz</a> ( ASC, MD5 , SHA1 )</td></tr></tbody></table><h2 id="解压latest-win64-zip"><a href="#解压latest-win64-zip" class="headerlink" title="解压latest-win64.zip"></a>解压latest-win64.zip</h2><blockquote><p>latest-win64.zip解压之后会产生两个文件目录nexus-3.19.1-01和sonatyp-work</p></blockquote><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/fa6e9d3c7006b52a3fc06830a5345a42.png" alt title>                </div>                <div class="image-caption"></div>            </figure><h2 id="启动nexus"><a href="#启动nexus" class="headerlink" title="启动nexus"></a>启动nexus</h2><p>cmd中直接运行<code>nexus-3.19.1-01/bin/nexus.exe /run</code> ，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">D:\installsoft\maven\nexus\nexus-3.19.1-01\bin&gt;nexus.exe /run</span><br></pre></td></tr></table></figure><p>如果输出中出现了下面的异常请忽略</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java.io.UnsupportedEncodingException: Encoding GBK is not supported yet (feel free to submit a patch)</span><br></pre></td></tr></table></figure><p>浏览器中打开</p><blockquote><p><a href="http://localhost:8081/" target="_blank" rel="noopener">http://localhost:8081/</a></p></blockquote><p>效果如下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/1a651ecf45653b3f3d3ef5e2fa2fc096.png" alt title>                </div>                <div class="image-caption"></div>            </figure><h2 id="登录Nexus"><a href="#登录Nexus" class="headerlink" title="登录Nexus"></a>登录Nexus</h2><p>点击上图右上角的<code>Sign in</code>，输入用户名和密码，nexus默认用户名是<code>admin</code></p><p>nexus这个版本的密码是第一次启动的时候生成的，密码位于下面的文件中：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">安装目录/sonatype-work/nexus3/admin.password</span><br></pre></td></tr></table></figure><p>登录成功后会弹出一些设置，如下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/9a486efb871f9c46f3025df7ba97b469.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>点击<code>Next</code>，设置新的登录密码（新密码要保存好），如下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/68d59c829641f70e582aedc4f5581cb9.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>点击<code>Next</code>-&gt;<code>Finish</code>完成设置。</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/e06d91c86e949f9ddc2c7c24057ece65.png" alt title>                </div>                <div class="image-caption"></div>            </figure><h2 id="其他一些常见的操作"><a href="#其他一些常见的操作" class="headerlink" title="其他一些常见的操作"></a>其他一些常见的操作</h2><h3 id="停止Nexus的命令"><a href="#停止Nexus的命令" class="headerlink" title="停止Nexus的命令"></a>停止Nexus的命令</h3><p>启动的cmd窗口中按：<code>ctrl+c</code>，可以停止Nexus。</p><h3 id="修改启动端口"><a href="#修改启动端口" class="headerlink" title="修改启动端口"></a>修改启动端口</h3><p>默认端口是8081，如果和本机有冲突，可以在下面的文件中修改：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nexus-3.19.1-01\etc\nexus-default.properties</span><br></pre></td></tr></table></figure><blockquote><p>nexus使用java开发的web项目，内置了jetty web容器，所以可以直接运行。</p></blockquote><h1 id="Linux安装Nexus私服"><a href="#Linux安装Nexus私服" class="headerlink" title="Linux安装Nexus私服"></a>Linux安装Nexus私服</h1><h2 id="下载安装包"><a href="#下载安装包" class="headerlink" title="下载安装包"></a>下载安装包</h2><p>下载linux版本的nexus安装包，选择<code>latest-unix.tar.gz</code>文件，将安装包放在<code>/opt/nexus/</code>目录。</p><h2 id="解压"><a href="#解压" class="headerlink" title="解压"></a>解压</h2><figure class="highlight plain"><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">[root@test1117 nexus]# tar -zvxf latest-unix.tar.gz</span><br><span class="line">[root@test1117 nexus]# lslatest-unix.tar.gz  nexus-3.19.1-01  sonatype-work</span><br></pre></td></tr></table></figure><h2 id="启动"><a href="#启动" class="headerlink" title="启动"></a>启动</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[root@test1117 bin]# /opt/nexus/nexus-3.19.1-01/bin/nexus start</span><br><span class="line">WARNING: ************************************************************</span><br><span class="line">WARNING: Detected execution as &quot;root&quot; user.  This is NOT recommended!</span><br><span class="line">WARNING: ************************************************************</span><br><span class="line">Starting nexus</span><br></pre></td></tr></table></figure><blockquote><p>我上面使用的是root用户操作的，为了安全性，你们最好自己创建个用户来操作。</p></blockquote><h2 id="开放端口"><a href="#开放端口" class="headerlink" title="开放端口"></a>开放端口</h2><p>在<code>/etc/sysconfig/iptables</code>文件中加入下面内容：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-A INPUT -p tcp -m state --state NEW -m tcp --dport 8081 -j ACCEPT</span><br></pre></td></tr></table></figure><p>执行下面命令，让上面配置生效：</p><figure class="highlight plain"><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">[root@test1117 bin]# service iptables restart</span><br><span class="line">Redirecting to /bin/systemctl restart  iptables.service</span><br></pre></td></tr></table></figure><h2 id="验证效果"><a href="#验证效果" class="headerlink" title="验证效果"></a>验证效果</h2><p>访问 <code>http://nexus私服所在的机器ip:8081/</code><br>出现下面效果表示一切ok。</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/944d22826e6d1c1f23237d4eeb96578e.png" alt title>                </div>                <div class="image-caption"></div>            </figure><h2 id="登录"><a href="#登录" class="headerlink" title="登录"></a>登录</h2><p>用户名为<code>admin</code>，密码在</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/opt/nexus/sonatype-work/nexus3/admin.password</span><br></pre></td></tr></table></figure><p>登录之后请请立即修改密码。</p><h1 id="Nexus中仓库分类"><a href="#Nexus中仓库分类" class="headerlink" title="Nexus中仓库分类"></a>Nexus中仓库分类</h1><p>前面我们说过，用户可以通过nexus去访问远程仓库，可以将本地的构件发布到nexus中，nexus是如何支撑这些操作的呢？</p><p>nexus中有个仓库列表，里面包含了各种各样的仓库，有我们说的被代理的第三方远程仓库，如下图：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/53041d06b2787666c43cafc162270131.jpeg" alt title>                </div>                <div class="image-caption"></div>            </figure><p>上图中是nexus安装好默认自带的仓库列表，主要有3种类型：</p><ol><li><p>代理仓库</p></li><li><p>宿主仓库</p></li><li><p>仓库组</p></li></ol><h2 id="代理仓库"><a href="#代理仓库" class="headerlink" title="代理仓库"></a>代理仓库</h2><p>代理仓库主要是让使用者通过代理仓库来间接访问外部的第三方远程仓库的，如通过代理仓库访问maven中央仓库、阿里的maven仓库等等。代理仓库会从被代理的仓库中下载构件，缓存在代理仓库中以供maven用户使用。</p><p>我们在nexus中创建一个阿里云的maven代理仓库来看下过程如下。</p><p>Nexus仓库列表中点击<code>Create repository</code>按钮，如下图：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/d66c6f9c3a4b0204c89da351529d1823.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>进入添加页面，选择<code>maven2(proxy)</code>，这个表示<code>代理仓库</code>，如下图：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/4e539a251b6ac9695d3e8a96a5cafd6e.jpeg" alt title>                </div>                <div class="image-caption"></div>            </figure><p>输入远程仓库的信息，如下图：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/1bfade67f0048e9822c8811efee8664f.png" alt title>                </div>                <div class="image-caption"></div>            </figure><pre><code>第一个红框中输入仓库名称：maven-aliyun 第二个红框选择：Release，表示从这个仓库中下载稳定版的构件 第三个红框输入阿里云仓库地址：https://maven.aliyun.com/repository/public</code></pre><p>点击底部的<code>Create repository</code>按钮，创建完成，如下图：</p>{% image https://oss.caozhg.com/hexo/maven/86b0c6a58938437bafdd0abe4d83114a.jpeg '' '' %}<h2 id="宿主仓库"><a href="#宿主仓库" class="headerlink" title="宿主仓库"></a>宿主仓库</h2><p>宿主仓库主要是给我们自己用的，主要有2点作用</p><ol><li><p>将私有的一些构件通过nexus中网页的方式上传到宿主仓库中给其他同事使用</p></li><li><p>将自己开发好一些构件发布到nexus的宿主仓库中以供其他同事使用</p></li></ol><p>上面这2种操作，一会稍后会详解以及演示操作过程。</p><h2 id="仓库组"><a href="#仓库组" class="headerlink" title="仓库组"></a>仓库组</h2><p>maven用户可以从代理仓库和宿主仓库中下载构件至本地仓库，为了方便从多个代理仓库和宿主仓库下载构件，maven提供了仓库组，仓库组中可以有多个代理仓库和宿主仓库，而maven用户只用访问一个仓库组就可以间接的访问这个组内所有的仓库，仓库组中多个仓库是有顺序的，当maven用户从仓库组下载构件时，仓库组会按顺序依次在组内的仓库中查找组件，查找到了立即返回给本地仓库，所以一般情况我们会将速度快的放在前面。</p><p>仓库组内部实际上是没有构件内容的，他只是起到一个请求转发的作用，将maven用户下载构件的请求转发给组内的其他仓库处理。</p><p>nexus默认有个仓库组<code>maven-public</code>，如下：</p>{% image https://oss.caozhg.com/hexo/maven/1690e096ab5773c14b51bd344ee31c27.jpeg '' '' %}<p>点击一下<code>maven-public</code>这行记录，进去看一下，如下图：</p>{% image https://oss.caozhg.com/hexo/maven/88fef81f693e6083ccaa511497995298.png '' '' %}<blockquote><p>上图中第一个红框是这个仓库组对外的一个url，我们本地的maven可以通过这个url来从仓库组中下载构件至本地仓库。</p><p>第二个红框中是这个仓库组中的成员，目前包含了3个仓库，第1个是宿主的releases版本仓库，第1个是宿主快照版本的仓库，第3个是代理仓库（maven社区中央仓库的代理）。</p><p>刚才我们新增的<code>maven-aliyun</code>在左边，我们将其也加到右边的仓库成员（<code>Members</code>）列表，然后将<code>maven-aliyun</code>这个仓库放在第3个位置，这个仓库的速度比<code>maven-central</code>要快一些，能加速我们下载maven构件的速度，如下图：</p></blockquote>{% image https://oss.caozhg.com/hexo/maven/dbd5e5f44f3616962603d8c85819f13e.png '' '' %}<h1 id="配置本地Maven从nexus下载构件"><a href="#配置本地Maven从nexus下载构件" class="headerlink" title="配置本地Maven从nexus下载构件"></a>配置本地Maven从nexus下载构件</h1><p>介绍2种方式</p><h2 id="方式1：pom-xml的方式"><a href="#方式1：pom-xml的方式" class="headerlink" title="方式1：pom.xml的方式"></a>方式1：pom.xml的方式</h2><p>本次我们就从nexus默认仓库组中下载构件，先获取仓库组对外的地址，点击下图中的<code>copy</code>按钮，获取仓库组的地址：</p>{% image https://oss.caozhg.com/hexo/maven/a7aa3c3315e8586790672ace460a80d8.jpeg '' '' %}{% image https://oss.caozhg.com/hexo/maven/6f4c77d1055b5da97ca19530bca48cab.png '' '' %}<p>修改pom.xml，加入如下内容：</p><blockquote><p>注意下面<code>url</code>的地址为上面复制的地址。</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&lt;repositories&gt;</span><br><span class="line">    &lt;repository&gt;</span><br><span class="line">        &lt;id&gt;maven-nexus&lt;/id&gt;</span><br><span class="line">        &lt;url&gt;http://localhost:8081/repository/maven-public/&lt;/url&gt;</span><br><span class="line">        &lt;releases&gt;</span><br><span class="line">            &lt;enabled&gt;true&lt;/enabled&gt;</span><br><span class="line">        &lt;/releases&gt;</span><br><span class="line">        &lt;snapshots&gt;</span><br><span class="line">            &lt;enabled&gt;true&lt;/enabled&gt;</span><br><span class="line">        &lt;/snapshots&gt;</span><br><span class="line">    &lt;/repository&gt;</span><br><span class="line">&lt;/repositories&gt;</span><br></pre></td></tr></table></figure><p>由于nexus私服需要有用户名和密码登录才能访问，所以需要有凭证，凭证需要在settings.xml文件中配置，在<code>~/.m2/settings.xml</code>文件的<code>servers</code>元素中加入如下内容：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;server&gt;</span><br><span class="line">  &lt;id&gt;maven-nexus&lt;/id&gt;</span><br><span class="line">  &lt;username&gt;admin&lt;/username&gt;</span><br><span class="line">  &lt;password&gt;admin123&lt;/password&gt;</span><br><span class="line">&lt;/server&gt;</span><br></pre></td></tr></table></figure><blockquote><p>注意上面的<code>server-&gt;id</code>的值和<code>pom.xml中repository-&gt;id</code>的值一致，通过这个id关联找到凭证的。</p><p>server元素中的username和password你们根据自己的去编辑，我这边密码设置的是admin123</p></blockquote><h3 id="方式1示例"><a href="#方式1示例" class="headerlink" title="方式1示例"></a>方式1示例</h3><p>创建一个maven项目，打开idea，点击<code>File-&gt;New-&gt;Project</code>，选择<code>Maven</code>，如下：</p>{% image https://oss.caozhg.com/hexo/maven/d678155ae26a94fc448548e0e2cbe11a.jpeg '' '' %}<p>点击<code>Next</code>，输入项目坐标信息，如下：</p>{% image https://oss.caozhg.com/hexo/maven/cdeb09b9357f808ab7b5c5ae947ef845.png '' '' %}<p>点击<code>Next</code>，输入Project name 为<code>maven-chat05</code>，如下：</p>{% image https://oss.caozhg.com/hexo/maven/45586b4920a32775cb897c711bff1424.png '' '' %}<p>点击<code>Finish</code>，创建成功，如下：</p>{% image https://oss.caozhg.com/hexo/maven/458c0bffe3ff5cfcdb1a9ec42cc85b4f.jpeg '' '' %}<p>配置一下idea的maven环境，点击<code>File-&gt;Settings</code>，如下图：</p>{% image https://oss.caozhg.com/hexo/maven/13236335889472ebd69722116b4fc2c3.jpeg '' '' %}<p>点击上面的<code>OK</code>完成配置。</p><p>还原<code>~/.m2/settings.xml</code>的配置到初始状态，操作如下：</p><blockquote><p>将M2_HOME/conf/settings.xml复制熬~/.m2/settings.xml目录，如果存在先备份一个，然后进行覆盖。</p></blockquote><p>修改上面idea项目中的pom.xml文件，内容如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="line">&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;</span><br><span class="line">         xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span><br><span class="line">         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;</span><br><span class="line">    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;groupId&gt;com.javacode2018&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;maven-chat05&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;dependencies&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;com.alibaba&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;fastjson&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;1.2.62&lt;/version&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">    &lt;/dependencies&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;repositories&gt;</span><br><span class="line">        &lt;repository&gt;</span><br><span class="line">            &lt;id&gt;maven-nexus&lt;/id&gt;</span><br><span class="line">            &lt;url&gt;http://localhost:8081/repository/maven-public/&lt;/url&gt;</span><br><span class="line">            &lt;releases&gt;</span><br><span class="line">                &lt;enabled&gt;true&lt;/enabled&gt;</span><br><span class="line">            &lt;/releases&gt;</span><br><span class="line">            &lt;snapshots&gt;</span><br><span class="line">                &lt;enabled&gt;true&lt;/enabled&gt;</span><br><span class="line">            &lt;/snapshots&gt;</span><br><span class="line">        &lt;/repository&gt;</span><br><span class="line">    &lt;/repositories&gt;</span><br><span class="line"> </span><br><span class="line">&lt;/project&gt;</span><br></pre></td></tr></table></figure><p>删除本地仓库中以下几个目录：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">~\.m2\repository\com\alibaba</span><br></pre></td></tr></table></figure><p>maven-chat05项目目录中打开cmd运行：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn compile</span><br></pre></td></tr></table></figure><p>见证奇迹的时刻，输出如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat05&gt;mvn compile</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat05 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat05 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">Downloading from maven-nexus: http://localhost:8081/repository/maven-public/com/alibaba/fastjson/1.2.62/fastjson-1.2.62.pom</span><br><span class="line">Downloaded from maven-nexus: http://localhost:8081/repository/maven-public/com/alibaba/fastjson/1.2.62/fastjson-1.2.62.pom (9.7 kB at 5.1 kB/s)</span><br><span class="line">Downloading from maven-nexus: http://localhost:8081/repository/maven-public/com/alibaba/fastjson/1.2.62/fastjson-1.2.62.jar</span><br><span class="line">Downloaded from maven-nexus: http://localhost:8081/repository/maven-public/com/alibaba/fastjson/1.2.62/fastjson-1.2.62.jar (658 kB at 70 kB/s)</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat05 ---</span><br><span class="line">[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat05 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  16.083 s</span><br><span class="line">[INFO] Finished at: 2019-11-13T15:45:44+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>从输出中可以看出fastjson这个jar包从<code>maven-nexus</code>中下载了，下载地址正是我们nexus私服中的那个地址。</p><h2 id="方式2：镜像方式"><a href="#方式2：镜像方式" class="headerlink" title="方式2：镜像方式"></a>方式2：镜像方式</h2><p>关于什么是镜像，这里就不在做说明了，上篇文章中有介绍，可以移步过去看一下：<a href="/2023/02/22/Maven-%E4%BB%93%E5%BA%93%E8%AF%A6%E8%A7%A3/">仓库详解</a></p><p>镜像的方式主要修改<code>~/.m2/setting.xml</code>文件，需要修改2处理。</p><p>第1处：setting.xml的mirrors元素中加入如下配置：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;mirror&gt;</span><br><span class="line">  &lt;id&gt;mirror-nexus&lt;/id&gt;</span><br><span class="line">  &lt;mirrorOf&gt;*&lt;/mirrorOf&gt;</span><br><span class="line">  &lt;name&gt;nexus镜像&lt;/name&gt;</span><br><span class="line">  &lt;url&gt;http://localhost:8081/repository/maven-public/&lt;/url&gt;</span><br><span class="line">&lt;/mirror&gt;</span><br></pre></td></tr></table></figure><blockquote><p>上面<code>mirrorOf</code>配置的<code>*</code>，说明所有远程仓库都通过该镜像下载构件。</p><p>url：这个为nexus中仓库组的地址，上面方式一中有说过。</p></blockquote><p>第2处：由于nexus的url是需要用户名和密码才可以访问的，所以需要配置访问凭证，在<code>~/.m2/settings.xml</code>文件的`servers`元素中加入如下内容：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;server&gt;</span><br><span class="line">  &lt;id&gt;mirror-nexus&lt;/id&gt;</span><br><span class="line">  &lt;username&gt;admin&lt;/username&gt;</span><br><span class="line">  &lt;password&gt;admin123&lt;/password&gt;</span><br><span class="line">&lt;/server&gt;</span><br></pre></td></tr></table></figure><blockquote><p>注意上面的<code>server-&gt;id</code>的值和<code>mirror-&gt;id</code>的值需要一致，这样才能找到对应的凭证。</p></blockquote><h3 id="方式2示例"><a href="#方式2示例" class="headerlink" title="方式2示例"></a>方式2示例</h3><p>还是以方式1中的maven项目maven-chat05为例。</p><p>修改pom.xml，内容如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="line">&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;</span><br><span class="line">         xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span><br><span class="line">         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;</span><br><span class="line">    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;groupId&gt;com.javacode2018&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;maven-chat05&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;dependencies&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;com.alibaba&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;fastjson&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;1.2.62&lt;/version&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">    &lt;/dependencies&gt;</span><br><span class="line"> </span><br><span class="line">&lt;/project&gt;</span><br></pre></td></tr></table></figure><p><code>~/.m2/settings.xml</code>的<code>servers</code>元素中加入下面内容：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;server&gt;</span><br><span class="line">  &lt;id&gt;mirror-nexus&lt;/id&gt;</span><br><span class="line">  &lt;username&gt;admin&lt;/username&gt;</span><br><span class="line">  &lt;password&gt;admin123&lt;/password&gt;</span><br><span class="line">&lt;/server&gt;</span><br></pre></td></tr></table></figure><blockquote><p>注意上面username、password根据你们自己的进行配置。</p></blockquote><p><code>~/.m2/settings.xml</code>的<code>mirrors</code>元素中加入下面内容：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;mirror&gt;</span><br><span class="line">  &lt;id&gt;mirror-nexus&lt;/id&gt;</span><br><span class="line">  &lt;mirrorOf&gt;*&lt;/mirrorOf&gt;</span><br><span class="line">  &lt;name&gt;nexus镜像&lt;/name&gt;</span><br><span class="line">  &lt;url&gt;http://localhost:8081/repository/maven-public/&lt;/url&gt;</span><br><span class="line">&lt;/mirror&gt;</span><br></pre></td></tr></table></figure><p>删除本地仓库中以下几个目录：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">~\.m2\repository\com\alibaba</span><br></pre></td></tr></table></figure><p>maven-chat05项目目录中打开cmd运行：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn compile</span><br></pre></td></tr></table></figure><p>见证奇迹的时刻，输出如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat05&gt;mvn compile</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat05 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat05 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">Downloading from mirror-nexus: http://localhost:8081/repository/maven-public/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom</span><br><span class="line">Downloaded from mirror-nexus: http://localhost:8081/repository/maven-public/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom (0 B at 0 B/s)</span><br><span class="line">Downloading from mirror-nexus: http://localhost:8081/repository/maven-public/org/apache/maven/plugins/maven-plugins/23/maven-plugins-23.pom</span><br><span class="line">Downloaded from mirror-nexus: http://localhost:8081/repository/maven-public/org/apache/maven/plugins/maven-plugins/23/maven-plugins-23.pom (0 B at 0 B/s)</span><br><span class="line">Downloading from mirror-nexus: http://localhost:8081/repository/maven-public/org/apache/maven/maven-parent/22/maven-parent-22.pom</span><br><span class="line">Downloaded from mirror-nexus: http://localhost:8081/repository/maven-public/org/apache/maven/maven-parent/22/maven-parent-22.pom (0 B at 0 B/s)</span><br><span class="line">Downloading from mirror-nexus: http://localhost:8081/repository/maven-public/org/apache/apache/11/apache-11.pom</span><br><span class="line">Downloaded from mirror-nexus: http://localhost:8081/repository/maven-public/org/apache/apache/11/apache-11.pom (0 B at 0 B/s)</span><br><span class="line">Downloading from mirror-nexus: http://localhost:8081/repository/maven-public/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.jar</span><br><span class="line">Downloaded from mirror-nexus: http://localhost:8081/repository/maven-public/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.jar (0 B at 0 B/s)</span><br><span class="line">Downloading from mirror-nexus: http://localhost:8081/repository/maven-public/org/apache/maven/plugins/maven-compiler-plugin/3.1/maven-compiler-plugin-3.1.pom</span><br><span class="line">Downloaded from mirror-nexus: http://localhost:8081/repository/maven-public/org/apache/maven/plugins/maven-compiler-plugin/3.1/maven-compiler-plugin-3.1.pom (0 B at 0 B/s)</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  02:23 min</span><br><span class="line">[INFO] Finished at: 2019-11-13T16:05:43+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>输出内容比较多，只截取了部分输出，从输出中可以看出fastjson这个jar包从<code>mirror-nexus</code>中下载了，下载地址正是我们nexus私服中的那个地址，镜像的方式起效了，是不是感觉很爽，哈哈！</p><h1 id="本地构件发布到私服"><a href="#本地构件发布到私服" class="headerlink" title="本地构件发布到私服"></a>本地构件发布到私服</h1><p>经常用到的有2种</p><ol><li><p><strong>使用maven部署构件至nexus私服</strong></p></li><li><p><strong>手动部署第三方构件至nexus私服</strong>：比如我们第三方发给我们的一个包，比如短信发送商的jar包，这个包远程仓库是不存在的，我们要把这个包上传到私服供所有开发使用。</p></li></ol><p>下面我们来看一下这两种如何操作。</p><h2 id="使用maven部署构件至nexus私服"><a href="#使用maven部署构件至nexus私服" class="headerlink" title="使用maven部署构件至nexus私服"></a>使用maven部署构件至nexus私服</h2><p>我们创建maven项目的时候，会有一个pom.xml文件，里面有个version元素，这个是这个构件的版本号，可以去看一下上面我们刚创建的<code>maven-chat05</code>，默认是<code>1.0-SNAPSHOT</code>，这个以<code>-SNAPSHOT</code>结尾的表示是个快照版本，叫做<code>SNAPSHOT</code>版本，快照版本一般是不稳定的，会反复发布、测试、修改、发布。而最终会有一个稳定的可以发布的版本，是没有<code>-SNAPSHOT</code>后缀的，这个叫做<code>release</code>版本。</p><p>而nexus私服中存储用户的构件是使用的宿主仓库，这个我们上面也有说过，nexus私服中提供了两个默认的宿主仓库分别用来存放<code>SNAPSHOT</code>版本和<code>release</code>版本，如下图：</p>{% image https://oss.caozhg.com/hexo/maven/01bcb4aff5bd8cec9e2473fce655ceb3.png '' '' %}<p>上图中第1个红框的<code>maven-releases</code>宿主仓库用来存放用户自己release版本的构件。</p><p>第2个红框的<code>maven-snapshots</code>宿主仓库用来存放用户snapshot版本的构件。</p><p>上面两个仓库的地址可以点击后面的<code>copy</code>按钮获取。</p><p>操作分为3步</p><h3 id="第一步：修改pom-xml配置"><a href="#第一步：修改pom-xml配置" class="headerlink" title="第一步：修改pom.xml配置"></a>第一步：修改pom.xml配置</h3><p>我们需要将本地maven项目的构件发布到上面宿主仓库中，需要修改项目中pom.xml的配置，加入下面内容：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&lt;distributionManagement&gt;</span><br><span class="line">    &lt;repository&gt;</span><br><span class="line">        &lt;id&gt;release-nexus&lt;/id&gt;</span><br><span class="line">        &lt;url&gt;http://localhost:8081/repository/maven-releases/&lt;/url&gt;</span><br><span class="line">        &lt;name&gt;nexus私服中宿主仓库-&gt;存放/下载稳定版本的构件&lt;/name&gt;</span><br><span class="line">    &lt;/repository&gt;</span><br><span class="line">    &lt;snapshotRepository&gt;</span><br><span class="line">        &lt;id&gt;snapshot-nexus&lt;/id&gt;</span><br><span class="line">        &lt;url&gt;http://localhost:8081/repository/maven-snapshots/&lt;/url&gt;</span><br><span class="line">        &lt;name&gt;nexus私服中宿主仓库-&gt;存放/下载快照版本的构件&lt;/name&gt;</span><br><span class="line">    &lt;/snapshotRepository&gt;</span><br><span class="line">&lt;/distributionManagement&gt;</span><br><span class="line">`</span><br></pre></td></tr></table></figure><blockquote><p>上面2个url分别是上图中两个宿主仓库的地址。</p></blockquote><h3 id="第二步：修改settings-xml"><a href="#第二步：修改settings-xml" class="headerlink" title="第二步：修改settings.xml"></a>第二步：修改settings.xml</h3><p>上面地址需要登录才可以访问，所以需要配置凭证，这个需要在<code>~/.m2/settings.xml</code>中进行配置，在这个文件的<code>servers</code>元素中加入：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&lt;server&gt;</span><br><span class="line">  &lt;id&gt;release-nexus&lt;/id&gt;</span><br><span class="line">  &lt;username&gt;admin&lt;/username&gt;</span><br><span class="line">  &lt;password&gt;admin123&lt;/password&gt;</span><br><span class="line">&lt;/server&gt;</span><br><span class="line"> </span><br><span class="line">&lt;server&gt;</span><br><span class="line">  &lt;id&gt;snapshot-nexus&lt;/id&gt;</span><br><span class="line">  &lt;username&gt;admin&lt;/username&gt;</span><br><span class="line">  &lt;password&gt;admin123&lt;/password&gt;</span><br><span class="line">&lt;/server&gt;</span><br></pre></td></tr></table></figure><blockquote><p>注意上面第1个<code>server-&gt;id</code>的值需要和pom.xml中的<code>distributionManagement-&gt;repository-&gt;id</code>的值一致。</p><p>第2个<code>server-&gt;id</code>的值需要和pom.xml中的<code>distributionManagement-&gt;snapshotRepository-&gt;id</code>的值一致。</p></blockquote><h3 id="第三步：执行-mvn-deploy-命令"><a href="#第三步：执行-mvn-deploy-命令" class="headerlink" title="第三步：执行`mvn deploy`命令"></a>第三步：执行`mvn deploy`命令</h3><p>执行这个命令的时候，会对构件进行打包，然后上传到私服中。</p><p>这命令的原理，后面的文章中会具体介绍。</p><p>示例效果</p><p>我们来感受一下效果。</p><p>按照上面的配置修改<code>maven-chat03/pom.xml</code>文件和本地的<code>~/.m2/settings.xml</code>文件。</p><p>maven-chat05项目目录中打开cmd运行：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn deploy</span><br></pre></td></tr></table></figure><p>见证奇迹的时刻，输出如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat05&gt;mvn deploy</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat05 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat05 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat05 ---</span><br><span class="line">[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat05 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-chat05 ---</span><br><span class="line">[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!</span><br><span class="line">[INFO] skip non existing resourceDirectory D:\code\IdeaProjects\maven-chat05\src\test\resources</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ maven-chat05 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-chat05 ---</span><br><span class="line">[INFO] No tests to run.</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ maven-chat05 ---</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-install-plugin:2.4:install (default-install) @ maven-chat05 ---</span><br><span class="line">[INFO] Installing D:\code\IdeaProjects\maven-chat05\target\maven-chat05-1.0-SNAPSHOT.jar to C:\Users\Think\.m2\repository\com\javacode2018\maven-chat05\1.0-SNAPSHOT\maven-chat05-1.0-SNAPSHOT.jar</span><br><span class="line">[INFO] Installing D:\code\IdeaProjects\maven-chat05\pom.xml to C:\Users\Think\.m2\repository\com\javacode2018\maven-chat05\1.0-SNAPSHOT\maven-chat05-1.0-SNAPSHOT.pom</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-deploy-plugin:2.7:deploy (default-deploy) @ maven-chat05 ---</span><br><span class="line">Downloading from snapshot-nexus: http://localhost:8081/repository/maven-snapshots/com/javacode2018/maven-chat05/1.0-SNAPSHOT/maven-metadata.xml</span><br><span class="line">Uploading to snapshot-nexus: http://localhost:8081/repository/maven-snapshots/com/javacode2018/maven-chat05/1.0-SNAPSHOT/maven-chat05-1.0-20191113.083820-1.jar</span><br><span class="line">Uploaded to snapshot-nexus: http://localhost:8081/repository/maven-snapshots/com/javacode2018/maven-chat05/1.0-SNAPSHOT/maven-chat05-1.0-20191113.083820-1.jar (1.8 kB at 11 kB/s)</span><br><span class="line">Uploading to snapshot-nexus: http://localhost:8081/repository/maven-snapshots/com/javacode2018/maven-chat05/1.0-SNAPSHOT/maven-chat05-1.0-20191113.083820-1.pom</span><br><span class="line">Uploaded to snapshot-nexus: http://localhost:8081/repository/maven-snapshots/com/javacode2018/maven-chat05/1.0-SNAPSHOT/maven-chat05-1.0-20191113.083820-1.pom (1.2 kB at 10 kB/s)</span><br><span class="line">Downloading from snapshot-nexus: http://localhost:8081/repository/maven-snapshots/com/javacode2018/maven-chat05/maven-metadata.xml</span><br><span class="line">Uploading to snapshot-nexus: http://localhost:8081/repository/maven-snapshots/com/javacode2018/maven-chat05/1.0-SNAPSHOT/maven-metadata.xml</span><br><span class="line">Uploaded to snapshot-nexus: http://localhost:8081/repository/maven-snapshots/com/javacode2018/maven-chat05/1.0-SNAPSHOT/maven-metadata.xml (772 B at 9.2 kB/s)</span><br><span class="line">Uploading to snapshot-nexus: http://localhost:8081/repository/maven-snapshots/com/javacode2018/maven-chat05/maven-metadata.xml</span><br><span class="line">Uploaded to snapshot-nexus: http://localhost:8081/repository/maven-snapshots/com/javacode2018/maven-chat05/maven-metadata.xml (286 B at 3.4 kB/s)</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  6.156 s</span><br><span class="line">[INFO] Finished at: 2019-11-13T16:38:20+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>输出内容中有<code>Uploading to snapshot-nexus、Uploaded to snapshot-nexus</code> ，<code>snapshot-nexus</code>正是我们在pom.xml配置的快照版本的地址，上面输出内容中有具体的地址，和快照的地址也是一样的，上传成功了。</p><p>我们去nexus私服中看一下，访问nexus私服中快照版本仓库的地址：</p><blockquote><p><a href="http://localhost:8081/repository/maven-snapshots/" target="_blank" rel="noopener">http://localhost:8081/repository/maven-snapshots/</a></p></blockquote><p>出现如下页面：</p>{% image https://oss.caozhg.com/hexo/maven/55c7245a8634350b63f34e036a6e1b9b.png '' '' %}<p>点击上面的<code>bowse</code>连接，如下图，我们的构件上传成功了：</p>{% image https://oss.caozhg.com/hexo/maven/17af4f8ea7c29cd4360f19a672c85941.png '' '' %}<p>如果其他同事需要使用上面这个构件，只需要点击下图中的pom文件，右边会显示构件的坐标，然后可以拿去使用了，如下图：</p>{% image https://oss.caozhg.com/hexo/maven/8b8c0b5b062e6c693df34e2fde6afc10.jpeg '' '' %}<p>上面是将快照版本的发布到了nexus私服的快照宿主仓库了，下面我们再来操作一下将release稳定版本的发布到nexus私服，如下：</p><p>修改pom.xml文件的版本号，将<code>-SNAPSHOT</code>后缀去掉，去掉之后表示是release版本的了，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;version&gt;1.0&lt;/version&gt;</span><br></pre></td></tr></table></figure><p>cmd命令中执行：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn deploy</span><br></pre></td></tr></table></figure><p>输出：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat05&gt;mvn deploy</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat05 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat05 1.0</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat05 ---</span><br><span class="line">[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat05 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-chat05 ---</span><br><span class="line">[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!</span><br><span class="line">[INFO] skip non existing resourceDirectory D:\code\IdeaProjects\maven-chat05\src\test\resources</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ maven-chat05 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-chat05 ---</span><br><span class="line">[INFO] No tests to run.</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ maven-chat05 ---</span><br><span class="line">[INFO] Building jar: D:\code\IdeaProjects\maven-chat05\target\maven-chat05-1.0.jar</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-install-plugin:2.4:install (default-install) @ maven-chat05 ---</span><br><span class="line">[INFO] Installing D:\code\IdeaProjects\maven-chat05\target\maven-chat05-1.0.jar to C:\Users\Think\.m2\repository\com\javacode2018\maven-chat05\1.0\maven-chat05-1.0.jar</span><br><span class="line">[INFO] Installing D:\code\IdeaProjects\maven-chat05\pom.xml to C:\Users\Think\.m2\repository\com\javacode2018\maven-chat05\1.0\maven-chat05-1.0.pom</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-deploy-plugin:2.7:deploy (default-deploy) @ maven-chat05 ---</span><br><span class="line">Uploading to release-nexus: http://localhost:8081/repository/maven-releases/com/javacode2018/maven-chat05/1.0/maven-chat05-1.0.jar</span><br><span class="line">Uploaded to release-nexus: http://localhost:8081/repository/maven-releases/com/javacode2018/maven-chat05/1.0/maven-chat05-1.0.jar (1.7 kB at 9.6 kB/s)</span><br><span class="line">Uploading to release-nexus: http://localhost:8081/repository/maven-releases/com/javacode2018/maven-chat05/1.0/maven-chat05-1.0.pom</span><br><span class="line">Uploaded to release-nexus: http://localhost:8081/repository/maven-releases/com/javacode2018/maven-chat05/1.0/maven-chat05-1.0.pom (1.2 kB at 12 kB/s)</span><br><span class="line">Downloading from release-nexus: http://localhost:8081/repository/maven-releases/com/javacode2018/maven-chat05/maven-metadata.xml</span><br><span class="line">Uploading to release-nexus: http://localhost:8081/repository/maven-releases/com/javacode2018/maven-chat05/maven-metadata.xml</span><br><span class="line">Uploaded to release-nexus: http://localhost:8081/repository/maven-releases/com/javacode2018/maven-chat05/maven-metadata.xml (304 B at 4.3 kB/s)</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  5.646 s</span><br><span class="line">[INFO] Finished at: 2019-11-13T16:48:44+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>输出中有<code>release-nexus</code>，说明使用了<code>pom.xml</code>中的<code>distributionManagement-&gt;repository-&gt;id</code>的值，上传地址是<code>http://localhost:8081/repository/maven-releases</code>。</p><p>打开nexus私服中release地址：</p><blockquote><p><a href="http://localhost:8081/repository/maven-releases/" target="_blank" rel="noopener">http://localhost:8081/repository/maven-releases/</a></p></blockquote>{% image https://oss.caozhg.com/hexo/maven/e6ec1222e795e7d7c42f937774fe4461.png '' '' %}<p>点击上面的<code>browse</code>连接，如下：</p>{% image https://oss.caozhg.com/hexo/maven/492afd67b60e0fe3c5fe2246958a6bdd.jpeg '' '' %}<p>成功了，是不是感觉很爽。</p><h2 id="手动部署构件至nexus私服"><a href="#手动部署构件至nexus私服" class="headerlink" title="手动部署构件至nexus私服"></a>手动部署构件至nexus私服</h2><p>操作步骤</p><p><strong>手动上传只支持发布稳定版本的构件</strong>，操作过程如下图：</p><p>登录nexus，按照下图的步骤依次点击：</p>{% image https://oss.caozhg.com/hexo/maven/3823926a84139358ba897b4aa0943286.png '' '' %}<p>图中第一行<code>maven-releases</code>宿主仓库就是存放用户自己构件的仓库，点击上图中列表中的第一行，进入上传页面，如下图：</p>{% image https://oss.caozhg.com/hexo/maven/881ae8f5e6d358f46e1cbc35da865cdb.png '' '' %}<p>上面页面中点击<code>Browse</code>选择本地的构件，然后输入其他坐标信息，点击<code>Upload</code>完成上传操作。</p><p>示例效果</p><p>我们把<code>maven-chat05\target\maven-chat05-1.0.jar</code>上传上去，如下：</p>{% image https://oss.caozhg.com/hexo/maven/e7626a952b8cbce920752d23d350ba0d.png '' '' %}<p>点击<code>Upload</code>完成上传操作。</p><p>访问如下地址：</p><pre><code>http://localhost:8081/#browse/browse:maven-releases</code></pre><p>可以看到上传好的构件，如下图：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/51288bc822741de62d67888ac17a1717.jpeg" alt title>                </div>                <div class="image-caption"></div>            </figure><h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p><strong>本文90%是实操部分，强烈建议大家去操作一遍，加深理解。如果有收获的帮忙分享一下，你们的支持也是我不断输出的一个动力，希望大家都能够学到东西！</strong></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;ol&gt;
&lt;li&gt;&lt;p&gt;maven3.6.1&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;开发工具idea&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;jdk1.8&lt;
      
    
    </summary>
    
      <category term="maven" scheme="https://www.caozhg.com/categories/maven/"/>
    
    
      <category term="maven" scheme="https://www.caozhg.com/tags/maven/"/>
    
  </entry>
  
  <entry>
    <title>Maven 仓库详解</title>
    <link href="https://www.caozhg.com/2023/02/22/Maven-%E4%BB%93%E5%BA%93%E8%AF%A6%E8%A7%A3/"/>
    <id>https://www.caozhg.com/2023/02/22/Maven-仓库详解/</id>
    <published>2023-02-22T02:03:00.000Z</published>
    <updated>2023-02-22T03:11:50.248Z</updated>
    
    <content type="html"><![CDATA[<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>在maven出现之前，项目中用到第三方jar包时，我们会把这些依赖的jar包拷贝到项目的lib目录中，如果我们开发了多个项目，这些jar包在各个项目目录中都有一份拷贝，这存在的一些问题：</p><ol><li>不方便jar包的管理，比如jar的升级、删除等操作 </li><li>对磁盘空间的重复占用</li></ol><p>主要还是不方便jar包的管理，maven很好的解决了这些问题，我们来看看maven管理依赖jar包的效果。</p><p>我来提几个问题，带着问题来看本篇内容</p><ol><li>maven是如何将依赖的jar引入项目的？</li><li>maven项目中依赖的jar是从哪里获取的？  </li><li>我们如何掌控这些jar的获取方式？ </li><li>maven是如何组织管理构件的？</li></ol><h1 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h1><ol><li><p>maven3.6.1</p></li><li><p>开发工具idea</p></li><li><p>jdk1.8</p></li></ol><h1 id="先来看一下maven项目案例"><a href="#先来看一下maven项目案例" class="headerlink" title="先来看一下maven项目案例"></a>先来看一下maven项目案例</h1><p>创建一个maven项目，打开idea，点击<code>File-&gt;New-&gt;Project</code>，选择<code>Maven</code>，如下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/1.jpeg" alt title>                </div>                <div class="image-caption"></div>            </figure><p>点击<code>Next</code>，输入项目坐标信息，如下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/2.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>点击<code>Next</code>，输入Project name 为<code>maven-chat03</code>，如下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/3.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>点击<code>Finish</code>，创建成功，如下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/4.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>我们看一下这个项目占用的磁盘大小：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/5.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>占用 29.9KB，下面我们在pom.xml中引入fastjson的依赖：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependencies&gt;</span><br><span class="line">    &lt;dependency&gt;</span><br><span class="line">        &lt;groupId&gt;com.alibaba&lt;/groupId&gt;</span><br><span class="line">        &lt;artifactId&gt;fastjson&lt;/artifactId&gt;</span><br><span class="line">        &lt;version&gt;1.2.62&lt;/version&gt;</span><br><span class="line">    &lt;/dependency&gt;</span><br><span class="line">&lt;/dependencies&gt;</span><br></pre></td></tr></table></figure><p> 创建一个Demo.java，如下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">package com.javacode;</span><br><span class="line"> </span><br><span class="line">import com.alibaba.fastjson.JSON;</span><br><span class="line"> </span><br><span class="line">public class Demo1 &#123;</span><br><span class="line">    public static void main(String[] args) &#123;</span><br><span class="line">        System.out.println(JSON.class);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>运行一下Demo1，输出：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">class com.alibaba.fastjson.JSON</span><br></pre></td></tr></table></figure><p>说明fastjson在项目中起效了，我们再来看一下项目的大小</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/6.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>上面一次是39kb，这次是49kb，大小增加了10KB，我们来看一下fastjson.jar的大小</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/7.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>这个jar包643kb，但是项目才49kb，这说明了什么？</p><p>说明了项目目录中没有包含这个jar包，只是对这个jar包做了一个引用。</p><p>如果系统中有很多项目，都采用同一个maven来引用依赖的jar包，那么这些jar只会在磁盘中存储一份，这些jar可以被其他所有的maven项目共享，项目只需要在pom.xml中通过maven坐标的方式来对这些jar进行引用，而不用再拷贝至项目中，若对jar包进行删除、升级版本直接修改pom.xml就可以了，非常方便。</p><p><strong>结论：maven采用引用的方式将依赖的jar引入进来，不对真实的jar进行拷贝，但是打包的时候，运行需要用到的jar都会被拷贝到安装包中。</strong></p><h1 id="Maven寻找依赖的jar"><a href="#Maven寻找依赖的jar" class="headerlink" title="Maven寻找依赖的jar"></a>Maven寻找依赖的jar</h1><p>我们可以看到，当我们项目中需要使用某些jar时，只需要将这些jar的maven坐标添加到pom.xml中就可以了，这背后maven是如何找到这些jar的呢？</p><p>maven官方为我们提供了一个站点，这个站点中存放了很多第三方常用的构建（jar、war、zip、pom等等），当我们需要使用这些构件时，只需将其坐标加入到pom.xml中，此时maven会自动将这些构建下载到本地一个目录，然后进行自动引用。</p><p>上面提到的maven站点，我们叫做maven中央仓库，本地目录叫做本地仓库。</p><p>默认情况下，当项目中引入依赖的jar包时，maven先在本地仓库检索jar，若本地仓库没有，maven再去从中央仓库寻找，然后从中央仓库中将依赖的构件下载到本地仓库，然后才可以使用，如果2个地方都没有，maven会报错。</p><p>下面我们来看看什么是仓库？</p><h1 id="Maven-仓库"><a href="#Maven-仓库" class="headerlink" title="Maven 仓库"></a>Maven 仓库</h1><p>在 Maven 中，任何一个依赖、插件或者项目构建的输出，都可以称之为构件。</p><p>在 Maven 中，仓库是一个位置，这个位置是用来存放各种第三方构件的，所有maven项目可以共享这个仓库中的构件。</p><p>Maven 仓库能帮助我们管理构件（主要是jar包），它就是放置所有jar文件（jar、war、zip、pom等等）的地方。</p><h2 id="仓库的分类"><a href="#仓库的分类" class="headerlink" title="仓库的分类"></a>仓库的分类</h2><p>主要分为2大类：</p><ol><li><p><strong>本地仓库</strong></p></li><li><p><strong>远程仓库</strong></p></li></ol><p><strong>而远程仓库又分为：中央仓库、私服、其他公共远程仓库</strong></p><p>当maven根据坐标寻找构件的时候，会首先查看本地仓库，如果本地仓库存在，则直接使用；如果本地不存在，maven会去远程仓库中查找，如果找到了，会将其下载到本地仓库中进行使用，如果本地和远程仓库都没有找到构件，maven会报错，构件只有在本地仓库中存在了，才能够被maven项目使用。</p><h3 id="本地仓库"><a href="#本地仓库" class="headerlink" title="本地仓库"></a>本地仓库</h3><p>默认情况下，maven本地仓库默认地址是<code>~/.m2/respository</code>目录，这个默认我们也可以在<code>~/.m2/settings.xml</code>文件中进行修改：</p><pre><code>&lt;localRepository&gt;本地仓库地址&lt;/localRepository&gt;</code></pre><p>当我们使用maven的时候，依赖的构件都会从远程仓库下载到本地仓库目录中。</p><p>Maven 的本地仓库，在安装 Maven 后并不会创建，当我们执行第一条 maven 命令的时候本地仓库才会创建，此时会从远程仓库下载构建到本地仓库给maven项目使用。</p><p>需要我们注意，默认情况下，<code>~/.m2/settings.xml</code>这个文件是不存在的（<code>~</code>是指用户目录，前面的文章中有介绍过，此处不再做说明），我们需要从Maven安装目录中拷贝<code>conf/settings.xml</code>文件，将<code>M2_HOME/conf/settings.xml</code>拷贝到<code>~/.m2</code>目录中，然后对<code>~/.m2/settings.xml</code>进行编辑，<code>M2_HOME/config/settings.xml</code>这个文件其实也是可以使用的，不过我们不建议直接使用，这个修改可能会影响其他所有使用者，还有修改了这个文件，也不利于以后maven的升级，如果我们使用<code>~/.m2/settings.xml</code>，而maven安装目录中的配置不动，升级的时候只需要替换一下安装包就好了，所以我们建议将maven安装目录中的<code>settings.xml</code>拷贝到<code>~/.m2</code>中进行编辑，这个是用户级别的，只会影响当前用户。</p><h3 id="远程仓库"><a href="#远程仓库" class="headerlink" title="远程仓库"></a>远程仓库</h3><p>最开始我们使用maven的时候，本地仓库中的构件是空的，此时maven必须要提供一种功能，要能够从外部获取这些构件，这个外部就是所谓的远程仓库，远程仓库可以有多个，当本地仓库找不到构件时，可以去远程仓库找，然后放置到本地仓库中进行使用。</p><h3 id="中央仓库"><a href="#中央仓库" class="headerlink" title="中央仓库"></a>中央仓库</h3><p>由于maven刚安装好的时候，本地仓库是空的，此时我们什么都没有配置，去执行maven命令的时候，我们会看到maven默认执行了一些下载操作，这个下载地址就是中央仓库的地址，这个地址是maven社区为我们提供的，是maven内置的一个默认的远程仓库地址，不需要用户去配置。</p><p>这个地址在maven安装包的什么地方呢？</p><p>我们使用的是3.6.1，在下面这个位置</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">apache-maven-3.6.1\lib\maven-model-builder-3.6.1.jar\org\apache\maven\model\pom-4.0.0.xml</span><br></pre></td></tr></table></figure><p>在pom-4.0.0.xml中，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&lt;repositories&gt;</span><br><span class="line">    &lt;repository&gt;</span><br><span class="line">      &lt;id&gt;central&lt;/id&gt;</span><br><span class="line">      &lt;name&gt;Central Repository&lt;/name&gt;</span><br><span class="line">      &lt;url&gt;https://repo.maven.apache.org/maven2&lt;/url&gt;</span><br><span class="line">      &lt;layout&gt;default&lt;/layout&gt;</span><br><span class="line">      &lt;snapshots&gt;</span><br><span class="line">        &lt;enabled&gt;false&lt;/enabled&gt;</span><br><span class="line">      &lt;/snapshots&gt;</span><br><span class="line">    &lt;/repository&gt;</span><br><span class="line">  &lt;/repositories&gt;</span><br></pre></td></tr></table></figure><p>就是：</p><blockquote><p><a href="https://repo.maven.apache.org/maven2" target="_blank" rel="noopener">https://repo.maven.apache.org/maven2</a></p></blockquote><p>可以去访问一下，如下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/11c323a0db375437be2a10662f4079ba.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>上面站点中包含了很多常用的构建。</p><p>中央仓库有几个特点：</p><ol><li><p>中央仓库是由maven官方社区提供给大家使用的</p></li><li><p>不需要我们手动去配置，maven内部集成好了</p></li><li><p>使用中央仓库时，机器必须是联网状态，需要可以访问中央仓库的地址</p></li></ol><p>中央仓库还为我们提供了一个检索构件的站点：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/db24bcd8917a94f3fbb788a3162dd2e2.jpeg" alt title>                </div>                <div class="image-caption"></div>            </figure><p>非常方便我们查找需要依赖的构件，大家可以去体验一下。</p><p>中央仓库中包含了这个世界上大多数流行的开源java构件，基本上所有的jave开发者都会使用这个仓库，一般我们需要的第三方构件在这里都可以找到。</p><h3 id="私服"><a href="#私服" class="headerlink" title="私服"></a>私服</h3><p>私服也是远程仓库中的一种，我们为什么需要私服呢？</p><p>如果我们一个团队中有几百个人在开发一些项目，都是采用maven的方式来组织项目，那么我们每个人都需要从远程仓库中把需要依赖的构件下载到本地仓库，这对公司的网络要求也比较高，为了节省这个宽带和加快下载速度，我们在公司内部局域网内部可以架设一台服务器，这台服务器起到一个代理的作用，公司里面的所有开发者去访问这个服务器，这台服务器将需要的构建返回给我们，如果这台服务器中也没有我们需要的构建，那么这个代理服务器会去远程仓库中查找，然后将其先下载到代理服务器中，然后再返回给开发者本地的仓库。</p><p>还有公司内部有很多项目之间会相互依赖，你可能是架构组的，你需要开发一些jar包给其他组使用，此时，我们可以将自己jar发布到私服中给其他同事使用，如果没有私服，可能需要我们手动发给别人或者上传到共享机器中，不过管理起来不是很方便。</p><p><strong>总体上来说私服有以下好处：</strong></p><ol><li><p>加速maven构件的下载速度</p></li><li><p>节省宽带</p></li><li><p>方便部署自己的构件以供他人使用</p></li><li><p>提高maven的稳定性，中央仓库需要本机能够访问外网，而如果采用私服的方式，只需要本机可以访问内网私服就可以了</p></li></ol><p><strong>关于私服，后面会专门有一篇文章会做详细介绍。</strong></p><h3 id="其他远程仓库"><a href="#其他远程仓库" class="headerlink" title="其他远程仓库"></a>其他远程仓库</h3><p>中央仓库是在国外的，访问速度不是特别快，所以有很多比较大的公司做了一些好事，自己搭建了一些maven仓库服务器，公开出来给其他开发者使用，比如像阿里、网易等等，他们对外提供了一些maven仓库给全球开发者使用，在国内的访问速度相对于maven中央仓库来说还是快了不少。</p><p>还有一些公司比较牛，只在自己公开的仓库中发布构件，这种情况如果要使用他们的构件时，需要去访问他们提供的远程仓库地址。</p><h3 id="构建文件的布局"><a href="#构建文件的布局" class="headerlink" title="构建文件的布局"></a>构建文件的布局</h3><p>我们来看一下构件在仓库的文件结构中是如何组成的？</p><p>这块我们以本地仓库来做说明，远程仓库中组织构件的方式和本地仓库是一样的，以fastjson在本地仓库中的信息为例来做说明，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;com.alibaba&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;fastjson&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;1.2.62&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure><p>上面是fastjson 1.2.62这个jar，我们看一下这个jar在本地仓库中的位置，如下图</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/8b14884795d0a34ce121f5084601ae59.png" alt title>                </div>                <div class="image-caption"></div>            </figure><p>fastjson这个jar的地址是：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">~\.m2\repository\com\alibaba\fastjson\1.2.62\fastjson-1.2.62.jar</span><br></pre></td></tr></table></figure><p><code>~\.m2\repository\</code>是仓库的目录，所有本地构件都位于该目录中，我们主要看一下后面的部分，是怎么构成的。</p><p>构件所在目录的构成如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">groupId+&quot;.&quot;+artifactId+&quot;.&quot;+版本号</span><br></pre></td></tr></table></figure><p>通过上面获取一个字符串，字符串由<code>groupId、artifactId、版本号</code>之间用<code>.</code>连接，然后将这个字符串中的<code>.</code>替换为文件目录分隔符然后创建多级目录。</p><p>而构件文件名称的组成如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[artifactId][-verion][-classifier].[type]</span><br></pre></td></tr></table></figure><p>上面的fastjson-1.2.62.jar信息如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">artifactId为fastjsonversion为1.2.62classifier为空type没有指定，默认为jar</span><br></pre></td></tr></table></figure><p>所以构件文件名称为<code>fastjson-1.2.62.jar</code>。</p><h1 id="关于构件版本问题"><a href="#关于构件版本问题" class="headerlink" title="关于构件版本问题"></a>关于构件版本问题</h1><p>平时我们开发项目的时候，打包测试，或者将自己开发的构建提供给他人使用时，中间我们反反复复的打包测试，会给使用方提供很多不稳定的版本，最终经过同事和测试反复验证修改，我们会发布一个稳定的版本。</p><p>在发布稳定版本之前，会有很多个不稳定的测试版本，我们版本我们称为快照版本，用SNAPSHOT表示，回头去看看本文开头搭建的<code>maven-cha03</code>的pom.xml文件，默认是快照版本的，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;</span><br></pre></td></tr></table></figure><p>version以<code>-SNAPSHOT</code>结尾的，表示这是一个不稳定的版本，这个版本我们最好只在公司内部测试的时候使用，最终发布的时候，我们需要将<code>-SNAPSHOT</code>去掉，然后发布一个稳定的版本，表示这个版本是稳定的，可以直接使用，这种稳定的版本我们叫做<code>release</code>版本。</p><p>当我们想控制构件获取的远程地址时，我们该怎么做呢？此时需要使用远程仓库的配置功能。</p><h1 id="Maven中远程仓库的配置"><a href="#Maven中远程仓库的配置" class="headerlink" title="Maven中远程仓库的配置"></a>Maven中远程仓库的配置</h1><p>此处我们讲解2种方式。</p><h2 id="方式1"><a href="#方式1" class="headerlink" title="方式1"></a>方式1</h2><p><strong>pom.xml中配置远程仓库，语法如下：</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;project&gt;</span><br><span class="line">    &lt;repositories&gt;</span><br><span class="line">        &lt;repository&gt;</span><br><span class="line">            &lt;id&gt;aliyun-releases&lt;/id&gt;</span><br><span class="line">            &lt;url&gt;https://maven.aliyun.com/repository/public&lt;/url&gt;</span><br><span class="line">            &lt;releases&gt;</span><br><span class="line">                &lt;enabled&gt;true&lt;/enabled&gt;</span><br><span class="line">            &lt;/releases&gt;</span><br><span class="line">            &lt;snapshots&gt;</span><br><span class="line">                &lt;enabled&gt;false&lt;/enabled&gt;</span><br><span class="line">            &lt;/snapshots&gt;</span><br><span class="line">        &lt;/repository&gt;</span><br><span class="line">    &lt;/repositories&gt;</span><br><span class="line">&lt;/project&gt;</span><br></pre></td></tr></table></figure><p>在repositories元素下，可以使用repository子元素声明一个或者多个远程仓库。</p><p>repository元素说明：</p><ul><li><p>id：远程仓库的一个标识，中央仓库的id是<code>central</code>，所以添加远程仓库的时候，id不要和中央仓库的id重复，会把中央仓库的覆盖掉</p></li><li><p>url：远程仓库地址</p></li><li><p>releases：主要用来配置是否需要从这个远程仓库下载稳定版本构建</p></li><li><p>snapshots：主要用来配置是否需要从这个远程仓库下载快照版本构建</p></li></ul><p>releases和snapshots中有个<code>enabled</code>属性，是个boolean值，默认为true，表示是否需要从这个远程仓库中下载稳定版本或者快照版本的构建，一般使用第三方的仓库，都是下载稳定版本的构建。</p><p>快照版本的构建以<code>-SNAPSHOT</code>结尾，稳定版没有这个标识。</p><p>示例</p><p>来感受一下pom方式配置远程仓库的效果。</p><p>文本编辑器打开<code>maven-chat03/pom.xml</code>，将下面内容贴进去：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="line">&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;</span><br><span class="line">         xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span><br><span class="line">         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;</span><br><span class="line">    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;groupId&gt;com.javacode&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;maven-chat03&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;dependencies&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;com.alibaba&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;fastjson&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;1.2.62&lt;/version&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;2.2.1.RELEASE&lt;/version&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">    &lt;/dependencies&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;repositories&gt;</span><br><span class="line">        &lt;repository&gt;</span><br><span class="line">            &lt;id&gt;aliyun-releases&lt;/id&gt;</span><br><span class="line">            &lt;url&gt;https://maven.aliyun.com/repository/public&lt;/url&gt;</span><br><span class="line">            &lt;releases&gt;</span><br><span class="line">                &lt;enabled&gt;true&lt;/enabled&gt;</span><br><span class="line">            &lt;/releases&gt;</span><br><span class="line">            &lt;snapshots&gt;</span><br><span class="line">                &lt;enabled&gt;false&lt;/enabled&gt;</span><br><span class="line">            &lt;/snapshots&gt;</span><br><span class="line">        &lt;/repository&gt;</span><br><span class="line">    &lt;/repositories&gt;</span><br><span class="line"> </span><br><span class="line">&lt;/project&gt;</span><br></pre></td></tr></table></figure><blockquote><p>上面我们配置了一个远程仓库，地址是阿里云的maven仓库地址，<code>releases</code>的<code>enabled</code>为<code>true</code>,<code>snapshots</code>的<code>enabled</code>为<code>false</code>，表示这个远程仓库我们只允许下载稳定版本的构件，而不能从这个仓库中下载快照版本的构建。</p></blockquote><p>删除本地仓库中以下几个目录：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">~\.m2\repository\org\springframework~\.m2\repository\com\alibaba</span><br></pre></td></tr></table></figure><p>maven-chat03项目目录中打开cmd运行：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn compile</span><br></pre></td></tr></table></figure><p>输出如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><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">D:\code\IdeaProjects\maven-chat03&gt;mvn compile</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat03 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat03 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">Downloading from aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-starter-web/2.2.1.RELEASE/spring-boot-starter-web-2.2.1.RELEASE.pom</span><br><span class="line">Downloaded from aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-starter-web/2.2.1.RELEASE/spring-boot-starter-web-2.2.1.RELEASE.pom (3.3 kB at 5.1 kB/s)</span><br><span class="line">Downloading from aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-starters/2.2.1.RELEASE/spring-boot-starters-2.2.1.RELEASE.pom</span><br><span class="line">Downloaded from aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-starters/2.2.1.RELEASE/spring-boot-starters-2.2.1.RELEASE.pom (1.8 kB at 8.0 kB/s)</span><br><span class="line">Downloading from aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-parent/2.2.1.RELEASE/spring-boot-parent-2.2.1.RELEASE.pom</span><br><span class="line">Downloaded from aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-parent/2.2.1.RELEASE/spring-boot-parent-2.2.1.RELEASE.pom (1.8 kB at 8.6 kB/s)</span><br><span class="line">Downloaded from aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/spring-expression/5.2.1.RELEASE/spring-expression-5.2.1.RELEASE.jar (282 kB at 82 kB/s)</span><br><span class="line">Downloaded from aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/spring-webmvc/5.2.1.RELEASE/spring-webmvc-5.2.1.RELEASE.jar (946 kB at 219 kB/s)</span><br><span class="line">Downloaded from aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/spring-beans/5.2.1.RELEASE/spring-beans-5.2.1.RELEASE.jar (684 kB at 56 kB/s)</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat03 ---</span><br><span class="line">[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat03 ---</span><br><span class="line">[INFO] Changes detected - recompiling the module!</span><br><span class="line">[WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent!</span><br><span class="line">[INFO] Compiling 1 source file to D:\code\IdeaProjects\maven-chat03\target\classes</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  24.079 s</span><br><span class="line">[INFO] Finished at: 2019-11-12T15:33:27+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>输出中有很多<code>Downloaded from aliyun-releases</code>，<code>Downloaded from</code>后面跟的<code>aliyun-releases</code>就是上面我们在pom.xml中配置的远程仓库repository元素中的id，后面还可以看到很多下载地址，这个地址就是我们上面在pom.xml中指定的远程仓库的地址，可以看到项目中依赖的构建从我们指定的远程仓库中下载了。</p><p>pom中配置远程仓库的方式只对当前项目起效，如果我们需要对所有项目起效，我们可以下面的方式2，向下看。</p><h2 id="方式2"><a href="#方式2" class="headerlink" title="方式2"></a>方式2</h2><p>镜像的方式</p><p>如果仓库X可以提供仓库Y所有的内容，那么我们就可以认为X是Y的一个镜像，通俗点说，可以从Y获取的构件都可以从他的镜像中进行获取。</p><p>可以采用镜像的方式配置远程仓库，镜像在<code>settings.xml</code>中进行配置，对所有使用该配置的maven项目起效，配置方式如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;mirror&gt;</span><br><span class="line">  &lt;id&gt;mirrorId&lt;/id&gt;</span><br><span class="line">  &lt;mirrorOf&gt;repositoryId&lt;/mirrorOf&gt;</span><br><span class="line">  &lt;name&gt;Human Readable Name for this Mirror.&lt;/name&gt;</span><br><span class="line">  &lt;url&gt;http://my.repository.com/repo/path&lt;/url&gt;</span><br><span class="line">&lt;/mirror&gt;</span><br></pre></td></tr></table></figure><p>mirrors元素下面可以有多个mirror元素，每个mirror元素表示一个远程镜像，元素说明：</p><ul><li><p>id：镜像的id，是一个标识</p></li><li><p>name：镜像的名称，这个相当于一个描述信息，方便大家查看</p></li><li><p>url：镜像对应的远程仓库的地址</p></li><li><p>mirrorOf：指定哪些远程仓库的id使用这个镜像，这个对应pom.xml文件中repository元素的id，就是表示这个镜像是给哪些pom.xml文章中的远程仓库使用的，这里面需要列出远程仓库的id，多个之间用逗号隔开，<code>*</code>表示给所有远程仓库做镜像</p></li></ul><p>这里主要对mirrorOf再做一下说明，上面我们在项目中定义远程仓库的时候，pom.xml文件的repository元素中有个id，这个id就是远程仓库的id，而mirrorOf就是用来配置哪些远程仓库会走这个镜像去下载构件。</p><p>mirrorOf的配置有以下几种:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;mirrorOf&gt;*&lt;/mirrorOf&gt;</span><br></pre></td></tr></table></figure><blockquote><p>上面匹配所有远程仓库id，这些远程仓库都会走这个镜像下载构件</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;mirrorOf&gt;远程仓库1的id,远程仓库2的id&lt;/mirrorOf&gt;</span><br></pre></td></tr></table></figure><blockquote><p>上面匹配指定的仓库，这些指定的仓库会走这个镜像下载构件</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;mirrorOf&gt;*,! repo1&lt;/mirrorOf&gt;</span><br></pre></td></tr></table></figure><blockquote><p>上面匹配所有远程仓库，repo1除外，使用感叹号将仓库从匹配中移除。</p></blockquote><p>需要注意镜像仓库完全屏蔽了被镜像的仓库，所以当镜像仓库无法使用的时候，maven是无法自动切换到被镜像的仓库的，此时下载构件会失败，这个需要了解。</p><p>示例</p><p>将maven-chat03中的pom.xml修改为：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="line">&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;</span><br><span class="line">         xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span><br><span class="line">         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;</span><br><span class="line">    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;groupId&gt;com.javacode2018&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;maven-chat03&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;</span><br><span class="line"> </span><br><span class="line">    &lt;dependencies&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;com.alibaba&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;fastjson&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;1.2.62&lt;/version&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;2.2.1.RELEASE&lt;/version&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">    &lt;/dependencies&gt;</span><br><span class="line"> </span><br><span class="line">&lt;/project&gt;</span><br></pre></td></tr></table></figure><p>修改~/.m2/settings.xml，加入镜像配置，如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&lt;mirrors&gt;</span><br><span class="line">    &lt;mirror&gt;</span><br><span class="line">        &lt;id&gt;mirror-aliyun-releases&lt;/id&gt;</span><br><span class="line">        &lt;mirrorOf&gt;*&lt;/mirrorOf&gt;</span><br><span class="line">        &lt;name&gt;阿里云maven镜像&lt;/name&gt;</span><br><span class="line">        &lt;url&gt;https://maven.aliyun.com/repository/public&lt;/url&gt;</span><br><span class="line">    &lt;/mirror&gt;</span><br><span class="line">&lt;/mirrors&gt;</span><br></pre></td></tr></table></figure><blockquote><p>上面配置了一个阿里云的镜像，注意镜像的id是<code>mirror-aliyun-releases</code></p><p>下面我们就来验证一下镜像的效果。</p></blockquote><p>删除本地仓库中的以下几个目录：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">~\.m2\repository\org\springframework~\.m2\repository\com\alibaba</span><br></pre></td></tr></table></figure><p>maven-chat03项目目录中打开cmd运行：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn compile</span><br></pre></td></tr></table></figure><p>输出如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">D:\code\IdeaProjects\maven-chat03&gt;mvn compile</span><br><span class="line">[INFO] Scanning for projects...</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] -------------------&lt; com.javacode2018:maven-chat03 &gt;--------------------</span><br><span class="line">[INFO] Building maven-chat03 1.0-SNAPSHOT</span><br><span class="line">[INFO] --------------------------------[ jar ]---------------------------------</span><br><span class="line">Downloading from mirror-aliyun-releases: https://maven.aliyun.com/repository/public/com/alibaba/fastjson/1.2.62/fastjson-1.2.62.pom</span><br><span class="line">Downloaded from mirror-aliyun-releases: https://maven.aliyun.com/repository/public/com/alibaba/fastjson/1.2.62/fastjson-1.2.62.pom (9.7 kB at 17 kB/s)</span><br><span class="line">Downloading from mirror-aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-starter-web/2.2.1.RELEASE/spring-boot-starter-web-2.2.1.RELEASE.pom</span><br><span class="line">Downloaded from mirror-aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-starter-web/2.2.1.RELEASE/spring-boot-starter-web-2.2.1.RELEASE.pom (3.3 kB at 15 kB/s)</span><br><span class="line">Downloading from mirror-aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-starters/2.2.1.RELEASE/spring-boot-starters-2.2.1.RELEASE.pom</span><br><span class="line">Downloaded from mirror-aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-starters/2.2.1.RELEASE/spring-boot-starters-2.2.1.RELEASE.pom (1.8 kB at 8.3 kB/s)</span><br><span class="line">Downloading from mirror-aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-parent/2.2.1.RELEASE/spring-boot-parent-2.2.1.RELEASE.pom</span><br><span class="line">Downloaded from mirror-aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-parent/2.2.1.RELEASE/spring-boot-parent-2.2.1.RELEASE.pom (1.8 kB at 8.2 kB/s)</span><br><span class="line">Downloading from mirror-aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-dependencies/2.2.1.RELEASE/spring-boot-dependencies-2.2.1.RELEASE.pom</span><br><span class="line">Downloaded from mirror-aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-dependencies/2.2.1.RELEASE/spring-boot-dependencies-2.2.1.RELEASE.pom (127 kB at 311 kB/s)</span><br><span class="line">Downloading from mirror-aliyun-releases: https://maven.aliyun.com/repository/public/org/springframework/spring-framework-bom/5.2.1.RELEASE/spring-framework-bom-5.2.1.RELEASE.pom</span><br><span class="line">[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-chat03 ---</span><br><span class="line">[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!</span><br><span class="line">[INFO] Copying 0 resource</span><br><span class="line">[INFO]</span><br><span class="line">[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ maven-chat03 ---</span><br><span class="line">[INFO] Nothing to compile - all classes are up to date</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] BUILD SUCCESS</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br><span class="line">[INFO] Total time:  15.967 s</span><br><span class="line">[INFO] Finished at: 2019-11-12T16:44:57+08:00</span><br><span class="line">[INFO] ------------------------------------------------------------------------</span><br></pre></td></tr></table></figure><p>上面复制了部分内容，大家仔细看一下<code>Downloaded from</code>后面显示的是<code>mirror-aliyun-releases</code>，这个和settings.xml中镜像的id一致，表示我们配置的镜像起效了，所有依赖的构建都从镜像来获取了。</p><p><strong>关于镜像一个比较常用的用法是结合私服一起使用，由于私服可以代理所有远程仓库（包含中央仓库），因此对于maven用来来说，只需通过访问一个私服就可以间接访问所有外部远程仓库了，这块后面我们会在私服中做具体说明。</strong></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;p&gt;在maven出现之前，项目中用到第三方jar包时，我们会把这些依赖的jar包拷贝到项目的lib目录中，如果我们开发了多个项目，这些jar包在
      
    
    </summary>
    
      <category term="java" scheme="https://www.caozhg.com/categories/java/"/>
    
    
      <category term="maven" scheme="https://www.caozhg.com/tags/maven/"/>
    
  </entry>
  
  <entry>
    <title>maven 进阶知识</title>
    <link href="https://www.caozhg.com/2023/02/21/maven-%E8%BF%9B%E9%98%B6%E7%9F%A5%E8%AF%86/"/>
    <id>https://www.caozhg.com/2023/02/21/maven-进阶知识/</id>
    <published>2023-02-21T13:00:00.000Z</published>
    <updated>2023-02-21T13:48:41.104Z</updated>
    
    <content type="html"><![CDATA[<h3 id="Maven-仓库"><a href="#Maven-仓库" class="headerlink" title="Maven 仓库"></a>Maven 仓库</h3><p>Maven仓库分为三种：本地仓库（local）、远程（remote）和中央仓库（central）这三种，下面介绍一下这三种仓库的区别；</p><h4 id="本地仓库"><a href="#本地仓库" class="headerlink" title="本地仓库"></a>本地仓库</h4><p>本地仓库: Maven 的本地仓库，在安装 Maven 后并不会创建，它是在第一次执行 maven 命令的时候才被创建。运行 Maven 的时候，Maven 所需要的任何构件都是直接从本地仓库获取的。如果本地仓库没有，它会首先尝试从远程仓库下载构件至本地仓库，然后再使用本地仓库的构件。默认情况下，不管Linux还是 Windows，每个用户在自己的用户目录下都有一个路径名为 .m2/respository/ 的仓库目录。Maven 本地仓库默认被创建在 %USER_HOME% 目录下。要修改默认位置，在 %M2_HOME%\conf 目录中的 Maven 的 settings.xml 文件中定义另一个路径。</p><blockquote><p>构件：在 Maven 中，任何一个依赖、插件或者项目构建的输出，都可以称之为构件。</p></blockquote><h4 id="中央仓库"><a href="#中央仓库" class="headerlink" title="中央仓库"></a>中央仓库</h4><p>中央仓库：Maven 中央仓库是由 Maven 社区提供的仓库，其中包含了大量常用的库。中央仓库包含了绝大多数流行的开源Java构件，以及源码、作者信息、SCM、信息、许可证信息等。一般来说，简单的Java项目依赖的构件都可以在这里下载到。中央仓库是由 Maven 社区管理不需要配置同时需要通过网络才能访问。要浏览中央仓库的内容，maven 社区提供了一个 URL：<a href="http://search.maven.org/#browse" target="_blank" rel="noopener">http://search.maven.org/#browse</a> 使用这个仓库，开发人员可以搜索所有可以获取的代码库。</p><h4 id="远程仓库"><a href="#远程仓库" class="headerlink" title="远程仓库"></a>远程仓库</h4><p>远程仓库：如果 Maven 在中央仓库中也找不到依赖的文件，它会停止构建过程并输出错误信息到控制台。为避免这种情况，Maven 提供了远程仓库的概念，它是开发人员自己定制仓库，包含了所需要的代码库或者其他工程中用到的 jar 文件。<br>举例说明，使用下面的 pom.xml，Maven 将从远程仓库中下载该 pom.xml 中声明的所依赖的（在中央仓库中获取不到的）文件。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;</span><br><span class="line">   xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span><br><span class="line">   xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0</span><br><span class="line">   http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;</span><br><span class="line">   &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;</span><br><span class="line">   &lt;groupId&gt;com.companyname.projectgroup&lt;/groupId&gt;</span><br><span class="line">   &lt;artifactId&gt;project&lt;/artifactId&gt;</span><br><span class="line">   &lt;version&gt;1.0&lt;/version&gt;</span><br><span class="line">   &lt;dependencies&gt;</span><br><span class="line">      &lt;dependency&gt;</span><br><span class="line">         &lt;groupId&gt;com.companyname.common-lib&lt;/groupId&gt;</span><br><span class="line">         &lt;artifactId&gt;common-lib&lt;/artifactId&gt;</span><br><span class="line">         &lt;version&gt;1.0.0&lt;/version&gt;</span><br><span class="line">      &lt;/dependency&gt;</span><br><span class="line">   &lt;dependencies&gt;</span><br><span class="line">   &lt;repositories&gt;</span><br><span class="line">      &lt;repository&gt;</span><br><span class="line">         &lt;id&gt;companyname.lib1&lt;/id&gt;</span><br><span class="line">         &lt;url&gt;http://download.companyname.org/maven2/lib1&lt;/url&gt;</span><br><span class="line">      &lt;/repository&gt;</span><br><span class="line">      &lt;repository&gt;</span><br><span class="line">         &lt;id&gt;companyname.lib2&lt;/id&gt;</span><br><span class="line">         &lt;url&gt;http://download.companyname.org/maven2/lib2&lt;/url&gt;</span><br><span class="line">      &lt;/repository&gt;</span><br><span class="line">   &lt;/repositories&gt;</span><br><span class="line">&lt;/project&gt;</span><br></pre></td></tr></table></figure><h3 id="Maven-依赖搜索顺序"><a href="#Maven-依赖搜索顺序" class="headerlink" title="Maven 依赖搜索顺序"></a>Maven 依赖搜索顺序</h3><p>当我们执行 Maven 构建命令时，Maven 开始按照以下顺序查找依赖的库：</p><ul><li>步骤 1 － 在本地仓库中搜索，如果找不到，执行步骤 2，如果找到了则执行其他操作。</li><li>步骤 2 － 在中央仓库中搜索，如果找不到，并且有一个或多个远程仓库已经设置，则执行步骤 4，如果找到了则下载到本地仓库中以备将来引用。</li><li>步骤 3 － 如果远程仓库没有被设置，Maven 将简单的停滞处理并抛出错误（无法找到依赖的文件）。</li><li>步骤 4 － 在一个或多个远程仓库中搜索依赖的文件，如果找到则下载到本地仓库以备将来引用，否则 Maven 将停止处理并抛出错误（无法找到依赖的文件）。</li></ul><h3 id="Maven命令"><a href="#Maven命令" class="headerlink" title="Maven命令"></a>Maven命令</h3><p>maven 命令用mvn开头代表是mvn命令，下面列举一下常用的Maven 命令以及命令的作用；</p><ul><li>【mvn -help】 help命令作用为获取Maven的命令列表以及简单作用解释（英文的）；</li><li>【mvn -v】 v命令为查看安装的Maven版本信息，还包括Maven的安装路径，Java 的版本和路径，操作系统类别以及操作系统编码格式等等（我们在上一篇文章中也是通过使用 mvn -v命令来检查我们的Maven 环境变量是否安装无误）；</li><li>【mvn clean】 clean 命令是Maven中Clean生命周期中的一个阶段命令，用来清除上一次构建生成的文件；</li><li>【mvn compile】 compile命令是Maven中Default（默认）生命周期中的一个阶段命令，用来编译项目；</li><li>【mvn package】 package命令也是Maven中Default（默认）生命周期中的一个阶段命令，用来将项目打包，打包前会启动项目的测试代码以检查程序是否能正常启动；</li><li>【mvn install】 install命令也是Maven中Default（默认）生命周期中的一个阶段命令，可以将打包成功的jar包安装到本地仓库，供其它项目使用；</li></ul><p>通过mvn命令中的clean、compile、package就可以将你完成的项目按照pom文件中配置的打包方式打包成可执行文件啦！（一般打包成jar包可以直接通过java命令启动或者war包通过web容器启动，如tomcat）;刚才在介绍命令的时候说到了Maven的生命周期，下面给大家做个详细介绍。</p><h3 id="Maven的生命周期"><a href="#Maven的生命周期" class="headerlink" title="Maven的生命周期"></a>Maven的生命周期</h3><p>Maven 有以下三个标准的生命周期：clean：项目清理的处理、default(或 build)：项目部署的处理、site：项目站点文档创建的处理</p><h4 id="Clean-生命周期"><a href="#Clean-生命周期" class="headerlink" title="Clean 生命周期"></a>Clean 生命周期</h4><p>当我们执行 mvn post-clean 命令时，Maven 调用 clean 生命周期，它包含以下阶段：</p><ul><li>pre-clean：执行一些需要在clean之前完成的工作</li><li>clean：移除所有上一次构建生成的文件</li><li>post-clean：执行一些需要在clean之后立刻完成的工作</li></ul><h4 id="Default-Build-生命周期"><a href="#Default-Build-生命周期" class="headerlink" title="Default (Build) 生命周期"></a>Default (Build) 生命周期</h4><p>这是 Maven 的主要生命周期，被用于构建应用，包括下面的 23 个阶段：</p><ul><li>validate（校验）：校验项目是否正确并且所有必要的信息可以完成项目的构建过程。</li><li>initialize（初始化）：初始化构建状态，比如设置属性值。</li><li>generate-sources（生成源代码）：生成包含在编译阶段中的任何源代码。</li><li>process-sources（处理源代码）：处理源代码，比如说，过滤任意值。</li><li>generate-resources（生成资源文件）：生成将会包含在项目包中的资源文件。</li><li>process-resources （处理资源文件）：复制和处理资源到目标目录，为打包阶段最好准备。</li><li>compile（编译）：编译项目的源代码。</li><li>process-classes（处理类文件）：处理编译生成的文件，比如说对Java class文件做字节码改善优化。</li><li>generate-test-sources（生成测试源代码）：生成包含在编译阶段中的任何测试源代码。</li><li>process-test-sources（处理测试源代码）：处理测试源代码，比如说，过滤任意值。</li><li>generate-test-resources（生成测试资源文件）：为测试创建资源文件。</li><li>process-test-resources（处理测试资源文件）：复制和处理测试资源到目标目录。</li><li>test-compile（编译测试源码）：编译测试源代码到测试目标目录.</li><li>process-test-classes（处理测试类文件）：处理测试源码编译生成的文件。</li><li>test（测试）：使用合适的单元测试框架运行测试（Juint是其中之一）。</li><li>prepare-package（准备打包）：在实际打包之前，执行任何的必要的操作为打包做准备。</li><li>package（打包）：将编译后的代码打包成可分发格式的文件，比如JAR、WAR或者EAR文件。</li><li>pre-integration-test（集成测试前）：在执行集成测试前进行必要的动作。比如说，搭建需要的环境。</li><li>integration-test（集成测试）：处理和部署项目到可以运行集成测试环境中。</li><li>post-integration-test（集成测试后）：在执行集成测试完成后进行必要的动作。比如说，清理集成测试环境</li><li>verify （验证）：运行任意的检查来验证项目包有效且达到质量标准。</li><li>install（安装）：安装项目包到本地仓库，这样项目包可以用作其他本地项目的依赖</li><li>deploy（部署）：将最终的项目包复制到远程仓库中与其他开发者和项目共享。</li></ul><h4 id="Site-生命周期"><a href="#Site-生命周期" class="headerlink" title="Site 生命周期"></a>Site 生命周期</h4><p>Maven Site 插件一般用来创建新的报告文档、部署站点等。</p><ul><li>pre-site：执行一些需要在生成站点文档之前完成的工作</li><li>site：生成项目的站点文档</li><li>post-site：执行一些需要在生成站点文档之后完成的工作，并且为部署做准备</li><li>site-deploy：将生成的站点文档部署到特定的服务器上<br>Maven包括的这三个标准生命周期中，其中clean和默认生命周期是开发中最常使用的，而Site生命周期一般可能项目经理比较感兴趣，可以生成项目站点，包括依赖信息，开发人员信息，版本信息等等，开发中一般不用；</li></ul><blockquote><p>当执行【mvn compile】命令时，这里的compile是build生命周期中的一个阶段，它会默认执行在compile阶段之前的所有阶段如validate、initialize、generate-sources、process-sources、generate-resources、process-resources一直到最后执行compile编译程序。如果执行【mvn package】,则在package阶段之前的所有阶段默认都会执行；但是不同生命周期的阶段不受影响，也就是当我们执行package命令时，并不会执行Clean生命周期中的三个阶段；当然我们也可以同时执行不同生命周期中的不同阶段命令如【mvn clean package】这种形式，注意先后顺序即可。</p></blockquote><h3 id="Maven中的插件"><a href="#Maven中的插件" class="headerlink" title="Maven中的插件"></a>Maven中的插件</h3><p>当我们执行mvn clean命令时，真正帮我们实现清除target目录的所有生成构建其实是通过插件来完成的，Maven的生命周期是抽象的，实际需要插件来完成任务，这一过程是通过将插件的目标（goal）绑定到生命周期的具体阶段（phase）来完成的。如：将maven-compiler-plugin插件的compile目标绑定到default生命周期的compile阶段，完成项目的源代码编译：注意所有Maven的pom文件都继承于一个超父pom文件，不管你有没有显示声明这个父文件，当你在子pom文件中声明了和父插件一样的插件以后，将会覆盖父插件的属性。一个插件通常可以完成多个任务，每一个任务就叫做插件的一个目标。如执行mvn install命令时，调用的插件和执行的插件目标如下：</p><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/maven-1.png" alt title>                </div>                <div class="image-caption"></div>            </figure><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/maven/maven-2.png" alt title>                </div>                <div class="image-caption"></div>            </figure><table><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>generate-resouces</td><td>plugin:descriptor</td></tr><tr><td>process-resources</td><td>resources:resources</td></tr><tr><td>compile</td><td>compile:compile</td></tr><tr><td>process-test-resources</td><td>resources:testResources</td></tr><tr><td>test-compile</td><td>compile:testCompile</td></tr><tr><td>test</td><td>surefire:test</td></tr><tr><td>package</td><td>jar:jar <br> plugin:addPluginArtifactMetadata</td></tr><tr><td>install</td><td>install:install</td></tr><tr><td>deploy</td><td>deploy:deploy</td></tr></tbody></table><p>用户可以根据需要将任何插件目标绑定到任何生命周期的阶段，如：将maven-source-plugin的jar-no-fork目标绑定到default生命周期的package阶段，这样，以后在执行mvn package命令打包项目时，在package阶段之后会执行源代码打包，生成如：ehcache-core-2.5.0-sources.jar形式的源码包。</p><p>当然我们也可以通过插件来跳过阶段，如当我们执行【mvn package】命令时，也会执行Test阶段启动程序来检查程序是否能够正常启动，但有的时候我们不想在打包程序的时候执行测试阶段，而是跳过他，那么我们就可以通过插件来（当然我们也可以通过其它的方式跳过测试，插件的方式只是其中一种，另外的方式在后面的文章中进行介绍），如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- maven 打包时跳过测试 --&gt;</span><br><span class="line"> &lt;plugin&gt;</span><br><span class="line">     &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br><span class="line">     &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;</span><br><span class="line">     &lt;configuration&gt;</span><br><span class="line">          &lt;skip&gt;true&lt;/skip&gt;</span><br><span class="line">      &lt;/configuration&gt;</span><br><span class="line">  &lt;/plugin&gt;</span><br></pre></td></tr></table></figure><h3 id="一个简单的pom文件"><a href="#一个简单的pom文件" class="headerlink" title="一个简单的pom文件"></a>一个简单的pom文件</h3><p>以下pom文件为创建一个SpringBoot项目生成的默认文件：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><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></pre></td><td class="code"><pre><span class="line">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span><br><span class="line">&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span><br><span class="line">         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;</span><br><span class="line">    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;</span><br><span class="line">    &lt;!-- 简单说一下每个部分的作用 --&gt;</span><br><span class="line"></span><br><span class="line">    &lt;!--继承的父pom --&gt;</span><br><span class="line">    &lt;parent&gt;</span><br><span class="line">        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">        &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;</span><br><span class="line">        &lt;version&gt;2.3.1.RELEASE&lt;/version&gt;</span><br><span class="line">        &lt;relativePath/&gt; &lt;!-- lookup parent from repository --&gt;</span><br><span class="line">    &lt;/parent&gt;</span><br><span class="line">    &lt;groupId&gt;com.zlc&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;springbootdemo&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;</span><br><span class="line">    &lt;name&gt;springbootdemo&lt;/name&gt;</span><br><span class="line">    &lt;description&gt;Demo project for Spring Boot&lt;/description&gt;</span><br><span class="line">    &lt;properties&gt;</span><br><span class="line">        &lt;java.version&gt;1.8&lt;/java.version&gt;</span><br><span class="line">    &lt;/properties&gt;</span><br><span class="line"></span><br><span class="line">    &lt;!-- 项目依赖--&gt;</span><br><span class="line">    &lt;!-- 一个查询依赖的网址： https://mvnrepository.com/--&gt;</span><br><span class="line">    &lt;dependencies&gt;</span><br><span class="line">        &lt;!-- web依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;!-- lombok依赖 --&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;lombok&lt;/artifactId&gt;</span><br><span class="line">            &lt;optional&gt;true&lt;/optional&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;!--单元测试依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;</span><br><span class="line">            &lt;scope&gt;test&lt;/scope&gt;</span><br><span class="line">            &lt;exclusions&gt;</span><br><span class="line">                &lt;exclusion&gt;</span><br><span class="line">                    &lt;groupId&gt;org.junit.vintage&lt;/groupId&gt;</span><br><span class="line">                    &lt;artifactId&gt;junit-vintage-engine&lt;/artifactId&gt;</span><br><span class="line">                &lt;/exclusion&gt;</span><br><span class="line">            &lt;/exclusions&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">    &lt;/dependencies&gt;</span><br><span class="line"></span><br><span class="line">    &lt;build&gt;</span><br><span class="line">        &lt;!-- Maven插件--&gt;</span><br><span class="line">        &lt;plugins&gt;</span><br><span class="line">            &lt;plugin&gt;</span><br><span class="line">                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">                &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;</span><br><span class="line">            &lt;/plugin&gt;</span><br><span class="line">        &lt;/plugins&gt;</span><br><span class="line">    &lt;/build&gt;</span><br><span class="line">&lt;/project&gt;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h3 id=&quot;Maven-仓库&quot;&gt;&lt;a href=&quot;#Maven-仓库&quot; class=&quot;headerlink&quot; title=&quot;Maven 仓库&quot;&gt;&lt;/a&gt;Maven 仓库&lt;/h3&gt;&lt;p&gt;Maven仓库分为三种：本地仓库（local）、远程（remote）和中央仓库（centra
      
    
    </summary>
    
      <category term="java" scheme="https://www.caozhg.com/categories/java/"/>
    
    
      <category term="maven" scheme="https://www.caozhg.com/tags/maven/"/>
    
      <category term="pom" scheme="https://www.caozhg.com/tags/pom/"/>
    
  </entry>
  
  <entry>
    <title>notepad-- 一个支持windows/linux/mac的文本编辑器，目标是要替换notepad++，来自中国。</title>
    <link href="https://www.caozhg.com/2023/02/13/notepad-%E4%B8%80%E4%B8%AA%E6%94%AF%E6%8C%81windows-linux-mac%E7%9A%84%E6%96%87%E6%9C%AC%E7%BC%96%E8%BE%91%E5%99%A8%EF%BC%8C%E7%9B%AE%E6%A0%87%E6%98%AF%E8%A6%81%E6%9B%BF%E6%8D%A2notepad-%EF%BC%8C%E6%9D%A5%E8%87%AA%E4%B8%AD%E5%9B%BD%E3%80%82/"/>
    <id>https://www.caozhg.com/2023/02/13/notepad-一个支持windows-linux-mac的文本编辑器，目标是要替换notepad-，来自中国。/</id>
    <published>2023-02-13T04:12:00.000Z</published>
    <updated>2023-02-13T04:20:41.923Z</updated>
    
    <content type="html"><![CDATA[<p>这是一个使用C++编写的文本编辑器Notepad–,可以支持Win/Linux/Mac平台。</p><p>我们的目标是要替换Notepad++，重点在国产Uos系统、Mac 系统上发展。</p><p>一个支持windows/linux/mac的文本编辑器，目标是要替换notepad++，来自中国。</p><p>对比Notepad++而言，我们的优势是可以跨平台，支持linux mac操作系统。</p><p>鉴于Notepad++作者的错误言论，Notepad–的意义在于：减少一点错误言论，减少一点自以为是。</p><a id="more"></a><ul><li><p>下载地址：<a href="https://gitee.com/cxasm/notepad--/releases" target="_blank" rel="noopener">https://gitee.com/cxasm/notepad--/releases</a></p></li><li><p>git地址：<a href="https://gitee.com/cxasm/notepad--/" target="_blank" rel="noopener">https://gitee.com/cxasm/notepad--/</a></p></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;这是一个使用C++编写的文本编辑器Notepad–,可以支持Win/Linux/Mac平台。&lt;/p&gt;
&lt;p&gt;我们的目标是要替换Notepad++，重点在国产Uos系统、Mac 系统上发展。&lt;/p&gt;
&lt;p&gt;一个支持windows/linux/mac的文本编辑器，目标是要替换notepad++，来自中国。&lt;/p&gt;
&lt;p&gt;对比Notepad++而言，我们的优势是可以跨平台，支持linux mac操作系统。&lt;/p&gt;
&lt;p&gt;鉴于Notepad++作者的错误言论，Notepad–的意义在于：减少一点错误言论，减少一点自以为是。&lt;/p&gt;
    
    </summary>
    
      <category term="工具" scheme="https://www.caozhg.com/categories/%E5%B7%A5%E5%85%B7/"/>
    
    
      <category term="notepad--" scheme="https://www.caozhg.com/tags/notepad/"/>
    
      <category term="notepad++" scheme="https://www.caozhg.com/tags/notepad/"/>
    
  </entry>
  
  <entry>
    <title>mstsc远程慢、卡顿，关闭udp</title>
    <link href="https://www.caozhg.com/2023/02/09/mstsc%E8%BF%9C%E7%A8%8B%E6%85%A2%E3%80%81%E5%8D%A1%E9%A1%BF%EF%BC%8C%E5%85%B3%E9%97%ADudp/"/>
    <id>https://www.caozhg.com/2023/02/09/mstsc远程慢、卡顿，关闭udp/</id>
    <published>2023-02-09T07:52:00.000Z</published>
    <updated>2023-02-09T07:52:56.853Z</updated>
    
    <content type="html"><![CDATA[<h4 id="搜索运行或Windows-R中，输入：gpedit-msc"><a href="#搜索运行或Windows-R中，输入：gpedit-msc" class="headerlink" title="搜索运行或Windows+R中，输入：gpedit.msc"></a>搜索运行或Windows+R中，输入：gpedit.msc</h4><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/windows_mstsc/1.png" alt title>                </div>                <div class="image-caption"></div>            </figure><h4 id="依次点击-【计算机配置】-gt-【管理模板】-gt-【windows组件】-gt-【远程桌面服务】-gt-【远程桌面连接客户端】"><a href="#依次点击-【计算机配置】-gt-【管理模板】-gt-【windows组件】-gt-【远程桌面服务】-gt-【远程桌面连接客户端】" class="headerlink" title="依次点击:【计算机配置】&gt;【管理模板】&gt;【windows组件】&gt;【远程桌面服务】&gt;【远程桌面连接客户端】"></a>依次点击:【计算机配置】&gt;【管理模板】&gt;【windows组件】&gt;【远程桌面服务】&gt;【远程桌面连接客户端】</h4><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/windows_mstsc/2.png" alt title>                </div>                <div class="image-caption"></div>            </figure><h4 id="右侧【关闭客户端上的UDP】-功能，双击选择选择已启用"><a href="#右侧【关闭客户端上的UDP】-功能，双击选择选择已启用" class="headerlink" title="右侧【关闭客户端上的UDP】 功能，双击选择选择已启用"></a>右侧【关闭客户端上的UDP】 功能，双击选择选择已启用</h4><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="https://oss.caozhg.com/hexo/windows_mstsc/3.png" alt title>                </div>                <div class="image-caption"></div>            </figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h4 id=&quot;搜索运行或Windows-R中，输入：gpedit-msc&quot;&gt;&lt;a href=&quot;#搜索运行或Windows-R中，输入：gpedit-msc&quot; class=&quot;headerlink&quot; title=&quot;搜索运行或Windows+R中，输入：gpedit.msc&quot;&gt;&lt;/a
      
    
    </summary>
    
      <category term="windows" scheme="https://www.caozhg.com/categories/windows/"/>
    
    
  </entry>
  
</feed>
